Merge branch '3.6-dev'
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index fdabcbb..885e1b7 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -31,4 +31,35 @@
     target-branch: "3.5-dev"
     labels:
       - "javascript"
-      - "dependencies"
\ No newline at end of file
+      - "dependencies"
+  - package-ecosystem: "npm"
+    directory: "/docs/gremlint"
+    schedule:
+      interval: "daily"
+    target-branch: "3.5-dev"
+    labels:
+      - "javascript"
+      - "dependencies"
+  - package-ecosystem: "gomod"
+    directory: "/gremlin-go"
+    schedule:
+      interval: "daily"
+    target-branch: "3.5-dev"
+    labels:
+      - "go"
+      - "dependencies"
+  - package-ecosystem: "maven"
+    directory: "/"
+    schedule:
+      interval: "daily"
+    target-branch: "3.5-dev"
+    labels:
+      - "java"
+      - "dependencies"
+  - package-ecosystem: "github-actions"
+    directory: "/"
+    schedule:
+      interval: "daily"
+    target-branch: "3.5-dev"
+    labels:
+      - "dependencies"
diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml
index 5e581e3..3c0e731 100644
--- a/.github/workflows/build-test.yml
+++ b/.github/workflows/build-test.yml
@@ -14,6 +14,20 @@
           distribution: 'temurin'
       - name: Build with Maven
         run: mvn clean install -DskipTests -Dci --batch-mode -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
+  java-jdk17:
+    name: mvn clean install - jdk17
+    timeout-minutes: 45
+    needs: smoke
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - name: Set up JDK 17
+        uses: actions/setup-java@v3
+        with:
+          java-version: '17'
+          distribution: 'temurin'
+      - name: Build with Maven
+        run: mvn clean install -pl -:gremlin-javascript,-:gremlin-dotnet-source,-:gremlin-dotnet-tests,-:gremlin-go,-:gremlin-python -Dci --batch-mode -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
   java-jdk11:
     name: mvn clean install - jdk11
     timeout-minutes: 45
diff --git a/.mailmap b/.mailmap
index 892e4ec..27d9bc1 100644
--- a/.mailmap
+++ b/.mailmap
@@ -18,3 +18,9 @@
 Stephen Mallette                 <spmallette@users.noreply.github.com>
 Stephen Mallette                 <spmva@genoprime.com>
 Stephen Mallette                 <spmva@genprime.com>
+Valentyn Kahamlyk                <vkagamlyk@users.noreply.github.com>
+Valentyn Kahamlyk                <valentynk@bitquilltech.com>
+Jorge Bay-Gondra                 <jorgebaygondra@gmail.com>
+Jorge Bay-Gondra                 <jorgebaygondra@gmail.com>
+
+
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 7437037..4db0a9a 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -16,6 +16,41 @@
 ////
 = TinkerPop3 CHANGELOG
 
+== TinkerPop 3.7.0 (NOT OFFICIALLY NAMED YET)
+
+image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/images/gremlin-standing.png[width=185]
+
+[[release-3-7.0]]
+=== TinkerPop 3.7.0 (Release Date: NOT OFFICIALLY RELEASED YET)
+
+This release also includes changes from <<release-3-6-XXX, 3.6.XXX>>.
+
+* Removed `connectOnStartup` configuration option from gremlin-javascript.
+* Changed `Gremlin.version()` to read from the more specificly named `tinkerpop-version` attribute.
+* Added warning on vertex property cardinality mismatch when reading GraphML.
+* Bumped to `ws` 8.x for `gremlin-javascript`.
+* Added support for mid-traversal `E()`-steps to Gremlin core and GLV's.
+* Added nullable annotations to Gremlin.NET.
+* Bumped Objenesis to 3.3 in `gremlin-shaded`.
+* Moved Java serializer, message and token classes from `gremlin-driver` to a new `gremlin-util` module.
+* Moved `SimpleSocketServer` and its initializers to a new `gremlin-tools/gremlin-socket-server` module.
+* Configured `gremlin-socket-server` to build a docker image which can be used for testing GLV's. (Can be skipped with -DskipImageBuild)
+* Reduced dependency from `gremlin-server` onto `gremlin-driver` to a test scope only.
+* Added `RequestOptions` and `RequestOptionsBuilder` types to Go GLV to encapsulate per-request settings and bindings.
+* Added `SubmitWithOptions()` methods to `Client` and `DriverRemoteConnection` in Go GLV to pass `RequestOptions` to the server.
+* Changed default behavior for returning properties on graph elements for OLTP queries so that properties are now returned.
+* Detachment is no longer performed in `TraverserIterator`.
+* Added `materializeProperties` request option to control properties serialization.
+* Modified serializers in to handle serialization and deserialization of properties.
+* Added functional properties to the graph structure components for .NET, GO and Python.
+* Modified the 1GremlinScriptChecker1 to extract the `materializeProperties` request option.
+* `Neo4jVertexProperty` no longer throw Exception for `properties()`, but return empty `Iterable`.
+* Removed deprecated `getInstance()` method for grammar `Visitor` implementations.
+* Bumped Groovy to 4.0.9.
+* Bumped GMavenPlus to 2.1.0.
+* Bumped Spark to 3.3.2.
+* Enabled building and testing with JDK 17.
+
 == TinkerPop 3.6.0 (Tinkerheart)
 
 image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/images/gremlin-victorian.png[width=185]
diff --git a/LICENSE b/LICENSE
index 1e747a9..47708b1 100644
--- a/LICENSE
+++ b/LICENSE
@@ -209,5 +209,6 @@
 
      bootstrap 5.0.0 (http://getbootstrap.com/) - for details, see licenses/bootstrap
      jquery 1.11.0 (https://jquery.com/) - for details, see licenses/jquery
-     normalize.css 2.1.2 (http://necolas.github.io/normalize.css/) - for details, see licenses/normalize
-     prism.css/js 1.27.0 (http://prismjs.com) - for details, see licenses/prism
\ No newline at end of file
+     normalize.css 2.1.2 (https://necolas.github.io/normalize.css/) - for details, see licenses/normalize
+     prism.css/js 1.27.0 (https://prismjs.com) - for details, see licenses/prism
+     wow.js 1.1.2 (https://wowjs.uk/) - for details, see licenses/wow
\ No newline at end of file
diff --git a/docker/gremlin-server/gremlin-server-integration-krb5.yaml b/docker/gremlin-server/gremlin-server-integration-krb5.yaml
index e7205be..16d7bf0 100644
--- a/docker/gremlin-server/gremlin-server-integration-krb5.yaml
+++ b/docker/gremlin-server/gremlin-server-integration-krb5.yaml
@@ -34,11 +34,11 @@
                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.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 }}
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV2d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV2d0] }}
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerGremlinV1d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV1d0] }}
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1 }
+  - { className: org.apache.tinkerpop.gremlin.util.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: {}}
diff --git a/docker/gremlin-server/gremlin-server-integration-secure.yaml b/docker/gremlin-server/gremlin-server-integration-secure.yaml
index 52f7d08..759d9bd 100644
--- a/docker/gremlin-server/gremlin-server-integration-secure.yaml
+++ b/docker/gremlin-server/gremlin-server-integration-secure.yaml
@@ -34,11 +34,11 @@
                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.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 }}
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV2d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV2d0] }}
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerGremlinV1d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV1d0] }}
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1 }
+  - { className: org.apache.tinkerpop.gremlin.util.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: {}}
diff --git a/docker/gremlin-server/gremlin-server-integration.yaml b/docker/gremlin-server/gremlin-server-integration.yaml
index 3b80082..4b0e4c6 100644
--- a/docker/gremlin-server/gremlin-server-integration.yaml
+++ b/docker/gremlin-server/gremlin-server-integration.yaml
@@ -37,11 +37,11 @@
                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.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 }}
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV2d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV2d0] }}
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerGremlinV1d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV1d0] }}
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1 }
+  - { className: org.apache.tinkerpop.gremlin.util.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: {}}
diff --git a/docs/gremlint/package-lock.json b/docs/gremlint/package-lock.json
index 5c6e269..8d1e592 100644
--- a/docs/gremlint/package-lock.json
+++ b/docs/gremlint/package-lock.json
@@ -11801,9 +11801,9 @@
       }
     },
     "node_modules/prettier": {
-      "version": "2.8.8",
-      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
-      "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
+      "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
       "dev": true,
       "bin": {
         "prettier": "bin-prettier.js"
@@ -14261,9 +14261,9 @@
       }
     },
     "node_modules/typescript": {
-      "version": "4.9.5",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
-      "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
+      "version": "4.7.4",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
+      "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
       "bin": {
         "tsc": "bin/tsc",
         "tsserver": "bin/tsserver"
@@ -23852,9 +23852,9 @@
       "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="
     },
     "prettier": {
-      "version": "2.8.8",
-      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
-      "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
+      "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
       "dev": true
     },
     "pretty-bytes": {
@@ -25674,9 +25674,9 @@
       }
     },
     "typescript": {
-      "version": "4.9.5",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
-      "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g=="
+      "version": "4.7.4",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
+      "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ=="
     },
     "unbox-primitive": {
       "version": "1.0.2",
diff --git a/docs/original/README b/docs/original/README
new file mode 100644
index 0000000..711beb5
--- /dev/null
+++ b/docs/original/README
@@ -0,0 +1 @@
+This directory holds original sized images that may have been re-sized for the website or other purposes.
\ No newline at end of file
diff --git a/docs/original/TinkerpopFuture-01-Home.png b/docs/original/TinkerpopFuture-01-Home.png
new file mode 100644
index 0000000..a7c719b
--- /dev/null
+++ b/docs/original/TinkerpopFuture-01-Home.png
Binary files differ
diff --git a/docs/original/TinkerpopFuture-02-Gremlin.png b/docs/original/TinkerpopFuture-02-Gremlin.png
new file mode 100644
index 0000000..c96fb99
--- /dev/null
+++ b/docs/original/TinkerpopFuture-02-Gremlin.png
Binary files differ
diff --git a/docs/original/TinkerpopFuture-03-Downloads.png b/docs/original/TinkerpopFuture-03-Downloads.png
new file mode 100644
index 0000000..5c1b6fd
--- /dev/null
+++ b/docs/original/TinkerpopFuture-03-Downloads.png
Binary files differ
diff --git a/docs/original/TinkerpopFuture-04-Providers.png b/docs/original/TinkerpopFuture-04-Providers.png
new file mode 100644
index 0000000..661373c
--- /dev/null
+++ b/docs/original/TinkerpopFuture-04-Providers.png
Binary files differ
diff --git a/docs/original/TinkerpopFuture-05-Community.png b/docs/original/TinkerpopFuture-05-Community.png
new file mode 100644
index 0000000..29d736c
--- /dev/null
+++ b/docs/original/TinkerpopFuture-05-Community.png
Binary files differ
diff --git a/docs/original/TinkerpopFuture-06-UseCases.png b/docs/original/TinkerpopFuture-06-UseCases.png
new file mode 100644
index 0000000..388c260
--- /dev/null
+++ b/docs/original/TinkerpopFuture-06-UseCases.png
Binary files differ
diff --git a/docs/original/ai/blueprints-character-1.ai b/docs/original/ai/blueprints-character-1.ai
new file mode 100644
index 0000000..89cc1e9
--- /dev/null
+++ b/docs/original/ai/blueprints-character-1.ai
Binary files differ
diff --git a/docs/original/ai/blueprints-character-2.ai b/docs/original/ai/blueprints-character-2.ai
new file mode 100644
index 0000000..dfc7c71
--- /dev/null
+++ b/docs/original/ai/blueprints-character-2.ai
Binary files differ
diff --git a/docs/original/ai/blueprints-character-3.ai b/docs/original/ai/blueprints-character-3.ai
new file mode 100644
index 0000000..21cbc7f
--- /dev/null
+++ b/docs/original/ai/blueprints-character-3.ai
Binary files differ
diff --git a/docs/original/ai/frames-character-1.ai b/docs/original/ai/frames-character-1.ai
new file mode 100644
index 0000000..cc4c831
--- /dev/null
+++ b/docs/original/ai/frames-character-1.ai
Binary files differ
diff --git a/docs/original/ai/frames-character-2.ai b/docs/original/ai/frames-character-2.ai
new file mode 100644
index 0000000..ce14786
--- /dev/null
+++ b/docs/original/ai/frames-character-2.ai
Binary files differ
diff --git a/docs/original/ai/frames-character-3.ai b/docs/original/ai/frames-character-3.ai
new file mode 100644
index 0000000..0c3eecd
--- /dev/null
+++ b/docs/original/ai/frames-character-3.ai
Binary files differ
diff --git a/docs/original/ai/furnace-character-1.ai b/docs/original/ai/furnace-character-1.ai
new file mode 100644
index 0000000..a091b5c
--- /dev/null
+++ b/docs/original/ai/furnace-character-1.ai
Binary files differ
diff --git a/docs/original/ai/furnace-character-2.ai b/docs/original/ai/furnace-character-2.ai
new file mode 100644
index 0000000..ebcfc20
--- /dev/null
+++ b/docs/original/ai/furnace-character-2.ai
Binary files differ
diff --git a/docs/original/ai/furnace-character-3.ai b/docs/original/ai/furnace-character-3.ai
new file mode 100644
index 0000000..e65c125
--- /dev/null
+++ b/docs/original/ai/furnace-character-3.ai
Binary files differ
diff --git a/docs/original/ai/gremlin-character-1.ai b/docs/original/ai/gremlin-character-1.ai
new file mode 100644
index 0000000..c7492b1
--- /dev/null
+++ b/docs/original/ai/gremlin-character-1.ai
Binary files differ
diff --git a/docs/original/ai/gremlin-character-2.ai b/docs/original/ai/gremlin-character-2.ai
new file mode 100644
index 0000000..0311bd9
--- /dev/null
+++ b/docs/original/ai/gremlin-character-2.ai
Binary files differ
diff --git a/docs/original/ai/pipes-character-1.ai b/docs/original/ai/pipes-character-1.ai
new file mode 100644
index 0000000..7d4ea10
--- /dev/null
+++ b/docs/original/ai/pipes-character-1.ai
Binary files differ
diff --git a/docs/original/ai/pipes-character-2.ai b/docs/original/ai/pipes-character-2.ai
new file mode 100644
index 0000000..a8eb41d
--- /dev/null
+++ b/docs/original/ai/pipes-character-2.ai
Binary files differ
diff --git a/docs/original/ai/pipes-character-3.ai b/docs/original/ai/pipes-character-3.ai
new file mode 100644
index 0000000..9234c8d
--- /dev/null
+++ b/docs/original/ai/pipes-character-3.ai
Binary files differ
diff --git a/docs/original/ai/rexster-character-1.ai b/docs/original/ai/rexster-character-1.ai
new file mode 100644
index 0000000..853732c
--- /dev/null
+++ b/docs/original/ai/rexster-character-1.ai
Binary files differ
diff --git a/docs/original/ai/rexster-character-2.ai b/docs/original/ai/rexster-character-2.ai
new file mode 100644
index 0000000..289cb79
--- /dev/null
+++ b/docs/original/ai/rexster-character-2.ai
Binary files differ
diff --git a/docs/original/ai/rexster-character-3.ai b/docs/original/ai/rexster-character-3.ai
new file mode 100644
index 0000000..44615e4
--- /dev/null
+++ b/docs/original/ai/rexster-character-3.ai
Binary files differ
diff --git a/docs/original/gremlin-twitch.png b/docs/original/gremlin-twitch.png
new file mode 100644
index 0000000..ceaa844
--- /dev/null
+++ b/docs/original/gremlin-twitch.png
Binary files differ
diff --git a/docs/original/twitch-channel-rules.png b/docs/original/twitch-channel-rules.png
new file mode 100644
index 0000000..dc281ca
--- /dev/null
+++ b/docs/original/twitch-channel-rules.png
Binary files differ
diff --git a/docs/site/home/benefits-use-cases.html b/docs/site/home/benefits-use-cases.html
index 7f617c9..4cb71e0 100644
--- a/docs/site/home/benefits-use-cases.html
+++ b/docs/site/home/benefits-use-cases.html
@@ -20,21 +20,32 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
     <link href="img/favicon.png" rel="shortcut icon"/>
-    <title>Apache TinkerPop</title>
+    <title>Apache TinkerPop: Benefits and Use Cases</title>
     <meta name="description" content="">
     <meta name="keywords" content="">
     <link href="css/bootstrap.min.css" rel="stylesheet">
-    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css"
-          integrity="sha512-5A8nwdMOWrSz20fDsjczgUidUBR8liPYU+WymTZP1lmY9G6Oc7HlZv156XqnsgNUzTyMefFTcsFH/tnJE/+xBg=="
-          crossorigin="anonymous" referrerpolicy="no-referrer"/>
+    <link href="css/font-awesome.css" rel="stylesheet"/>
     <link href="css/custome.css" rel="stylesheet">
     <link href="css/responsive.css" rel="stylesheet">
-    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.1/animate.css"
-          integrity="sha512-K2J6Yt6ElUYEMPcTr0wm555AAyiqkgYiUgPIW18FT88/aYSNDk0EvGjsln/TEu3ee/jaHf0xoXzFppSbBtUXbQ=="
-          crossorigin="anonymous" referrerpolicy="no-referrer"/>
-    <link rel="preconnect" href="https://fonts.googleapis.com">
-    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-    <link href="https://fonts.googleapis.com/css2?family=Raleway:wght@400;500;600;700&display=swap" rel="stylesheet">
+    <link href="css/animate.css" rel="stylesheet"/>
+    <link href="css/fonts.css" rel="stylesheet">
+    <!-- Matomo -->
+    <script>
+        var _paq = window._paq = window._paq || [];
+        /* We explicitly disable cookie tracking to avoid privacy issues */
+        _paq.push(['disableCookies']);
+        /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
+        _paq.push(['trackPageView']);
+        _paq.push(['enableLinkTracking']);
+        (function() {
+            var u="https://analytics.apache.org/";
+            _paq.push(['setTrackerUrl', u+'matomo.php']);
+            _paq.push(['setSiteId', '27']);
+            var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
+            g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
+        })();
+    </script>
+    <!-- End Matomo Code -->
 </head>
 <body>
 <!-- header -->
@@ -58,6 +69,21 @@
                         <li class="nav-item">
                             <a class="nav-link" href="download.html">Download</a>
                         </li>
+
+                        <li class="nav-item dropdown">
+                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown4" role="button" data-bs-toggle="dropdown" aria-expanded="false">
+                                Tools
+                            </a>
+                            <ul class="dropdown-menu" aria-labelledby="navbarDropdown4">
+                                <li><a class="dropdown-item" href="providers.html">Graph Systems</a></li>
+                                <li><a class="dropdown-item" href="community.html">Languages and Tools</a></li>
+                                <li><hr class="dropdown-divider"></li>
+                                <li><a class="dropdown-item" href="https://gremlify.com/">Gremlify: Try Gremlin</a></li>
+                                <li><a class="dropdown-item" href="https://tinkerpop.apache.org/gremlint">Gremlint: Lint Gremlin</a></li>
+                                <li><a class="dropdown-item" href="https://www.gremlator.com/">Gremlator: Translate Gremlin</a></li>
+                            </ul>
+                        </li>
+
                         <li class="nav-item dropdown">
                             <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
                                data-bs-toggle="dropdown" aria-expanded="false">
@@ -80,6 +106,7 @@
                             </ul>
 
                         </li>
+
                         <li class="nav-item dropdown">
                             <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown1" role="button"
                                data-bs-toggle="dropdown" aria-expanded="false">
@@ -109,48 +136,31 @@
 
                         </li>
                         <li class="nav-item dropdown">
-                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown3" role="button"
-                               data-bs-toggle="dropdown" aria-expanded="false">
+                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown3" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                                 Community
                             </a>
                             <ul class="dropdown-menu" aria-labelledby="navbarDropdown3">
-                                <li><a class="dropdown-item" href="https://groups.google.com/group/gremlin-users">User
-                                    Mailing List</a></li>
-                                <li><a class="dropdown-item"
-                                       href="https://lists.apache.org/list.html?dev@tinkerpop.apache.org">Developer
-                                    Mailing List</a></li>
-                                <li><a class="dropdown-item" href="https://discord.gg/ndMpKZcBEE" target="_blank"><img
-                                        src="img/discord_logo.png" class="nav-icon">Join us on Discord</a></li>
-                                <li><a class="dropdown-item" href="https://issues.apache.org/jira/browse/TINKERPOP/">Issue
-                                    Tracker</a></li>
-                                <li><a class="dropdown-item"
-                                       href="https://tinkerpop.apache.org/docs/current/dev/developer/#_contributing">Contributing</a>
-                                </li>
-                                <li><a class="dropdown-item" href="providers.html">Data System Support</a></li>
-                                <li><a class="dropdown-item" href="community.html">Languages and Tools</a></li>
-                                <li><a class="dropdown-item"
-                                       href="https://tinkerpop.apache.org/docs/current/dev/provider/#policies">Policies</a>
-                                </li>
-                                <li>
-                                    <hr class="dropdown-divider">
-                                </li>
-                                <li><a class="dropdown-item" href="https://github.com/apache/tinkerpop/"><img
-                                        src="img/github-logo.png" class="nav-icon">GitHub</a></li>
-                                <li><a class="dropdown-item" href="https://twitter.com/apachetinkerpop"><img
-                                        src="img/twitter-logo.png" class="nav-icon">Twitter</a></li>
+                                <li><a class="dropdown-item" href="https://discord.gg/kfebyvDM9H" target="_blank"><img src="img/discord-logo.png" class="nav-icon"/>Discord</a></li>
+                                <li><a class="dropdown-item" href="https://www.answeroverflow.com/c/838910279550238720"><img src="img/answer-overflow-logo.png" class="nav-icon"/>Answer Overflow</a></li>
+                                <li><a class="dropdown-item" href="https://stackoverflow.com/questions/tagged/gremlin"><img src="img/stack-overflow-logo.png" class="nav-icon"/>Stack Overflow</a></li>
+                                <li><a class="dropdown-item" href="https://groups.google.com/group/gremlin-users"><img src="img/mail.png" class="nav-icon"/>User Mailing List</a></li>
+                                <li><a class="dropdown-item" href="https://lists.apache.org/list.html?dev@tinkerpop.apache.org"><img src="img/mail.png" class="nav-icon"/>Developer Mailing List</a></li>
+                                <li><a class="dropdown-item" href="https://issues.apache.org/jira/browse/TINKERPOP/"><img src="img/jira-logo.png" class="nav-icon"/>Issue Tracker</a></li>
+                                <li><a class="dropdown-item" href="https://github.com/apache/tinkerpop/"><img src="img/github-logo.png" class="nav-icon"/>GitHub</a></li>
+                                <li><a class="dropdown-item" href="https://www.twitch.tv/apachetinkerpop"><img src="img/twitch-logo.png" class="nav-icon"/>Twitch</a></li>
+                                <li><a class="dropdown-item" href="https://twitter.com/apachetinkerpop"><img src="img/twitter-logo.png" class="nav-icon"/>Twitter</a></li>
+                                <li><a class="dropdown-item" href="https://www.youtube.com/@apachetinkerpop"><img src="img/youtube-logo.png" class="nav-icon"/>YouTube</a></li>
+                                <li><hr class="dropdown-divider"></li>
+                                <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/dev/developer/#_contributing">Contributing</a></li>
+                                <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/dev/provider/#policies">Policies</a></li>
                             </ul>
-
-                        </li>
-
-                        <li class="nav-item">
-                            <a class="nav-link" href="https://tinkerpop.apache.org/gremlint/">Gremlint</a>
                         </li>
                         <li class="nav-item dropdown">
-                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown4" role="button"
+                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown5" role="button"
                                data-bs-toggle="dropdown" aria-expanded="false">
                                 Apache Software
                             </a>
-                            <ul class="dropdown-menu" aria-labelledby="navbarDropdown4">
+                            <ul class="dropdown-menu" aria-labelledby="navbarDropdown5">
                                 <li><a class="dropdown-item" href="https://www.apache.org/">Apache Homepage</a></li>
                                 <li><a class="dropdown-item" href="https://www.apache.org/licenses/">License</a></li>
                                 <li><a class="dropdown-item"
@@ -314,9 +324,9 @@
         <div class="row d-flex justify-content-center">
             <div class="col-md-8 col-lg-6">
                 <div class="ju-box">
-                    <h2 class="ft-40 text-blue bold">Join Us on</h2>
-                    <p class="bold">Join us on our Discord Chat</p>
-                    <a href="https://discord.gg/ndMpKZcBEE"><img src="img/tpvewx.png" class="img-fluid mt-3" alt="img"></a>
+                    <h2 class="ft-40 text-blue bold">Join Us</h2>
+                    <p class="bold">Join us on our Discord Server</p>
+                    <a href="https://discord.gg/kfebyvDM9H"><img src="img/tpvewx.png" class="img-fluid mt-3" alt="img"></a>
                 </div>
             </div>
         </div>
@@ -330,15 +340,13 @@
             <div class="row">
                 <div class="col-md-4">
                     <div class="bold ft-25">Apache TinkerPop™</div>
-                    <p class="mt-2 mb-4">Apache TinkerPop™ is a graph computing framework for both graph databases
-                        (OLTP) and graph analytic systems (OLAP).</p>
+                    <p class="mt-2 mb-4">Apache TinkerPop™ is a graph computing framework for both graph databases (OLTP) and graph analytic systems (OLAP).</p>
                     <ul class="list-unstyled list-inline hover-op-low">
-                        <li class="list-inline-item"><a href="https://discord.gg/ndMpKZcBEE"><img
-                                src="img/social/discord.svg" class="img-fluid" alt="img"></a></li>
-                        <li class="list-inline-item"><a href="https://twitter.com/apachetinkerpop"><img
-                                src="img/social/twitter-square.svg" class="img-fluid" alt="img"></a></li>
-                        <li class="list-inline-item"><a href="https://github.com/apache/tinkerpop"><img
-                                src="img/social/github-box.svg" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://discord.gg/kfebyvDM9H"><img src="img/social/discord.svg" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://github.com/apache/tinkerpop"><img src="img/social/github-box.svg" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://www.twitch.tv/apachetinkerpop"><img src="img/social/twitch.png" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://twitter.com/apachetinkerpop"><img src="img/social/twitter-square.svg" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://www.youtube.com/@apachetinkerpop"><img src="img/social/youtube.png" class="img-fluid" alt="img"></a></li>
                     </ul>
                 </div>
                 <div class="col-md-4 ft-links">
@@ -349,6 +357,7 @@
                                 <li><a href="index.html">Home</a></li>
                                 <li><a href="download.html">Downloads</a></li>
                                 <li><a href="https://tinkerpop.apache.org/docs/current">Documentation</a></li>
+                                <li><a href="https://privacy.apache.org/policies/privacy-policy-public.html" target="_blank">Privacy Policy</a></li>
                             </ul>
                         </div>
                         <div class="col-lg-6">
@@ -373,7 +382,7 @@
         <div class="container">
             <div class="row">
                 <div class="col-12">
-                    Copyright © 2015-2022 The Apache Software Foundation
+                    Copyright © 2015-2023 The Apache Software Foundation
                 </div>
             </div>
         </div>
@@ -381,9 +390,7 @@
 </footer>
 <script src="js/jquery-1.11.1.js"></script>
 <script src="js/bootstrap.bundle.min.js"></script>
-<script src="https://cdnjs.cloudflare.com/ajax/libs/wow/1.1.2/wow.min.js"
-        integrity="sha512-Eak/29OTpb36LLo2r47IpVzPBLXnAMPAVypbSZiZ4Qkf8p/7S/XRG5xp7OKWPPYfJT6metI+IORkR5G8F900+g=="
-        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
+<script src="js/wow.min.js"></script>
 <script src="js/my.js"></script>
 </body>
 </html>
diff --git a/docs/site/home/community.html b/docs/site/home/community.html
index 890fc2f..6087975 100644
--- a/docs/site/home/community.html
+++ b/docs/site/home/community.html
@@ -19,22 +19,33 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
     <link href="img/favicon.png" rel="shortcut icon"/>
-    <title>Apache TinkerPop</title>
+    <title>Apache TinkerPop: Community</title>
     <meta name="description" content="">
     <meta name="keywords" content="">
     <link href="css/bootstrap.min.css" rel="stylesheet">
-    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css"
-          integrity="sha512-5A8nwdMOWrSz20fDsjczgUidUBR8liPYU+WymTZP1lmY9G6Oc7HlZv156XqnsgNUzTyMefFTcsFH/tnJE/+xBg=="
-          crossorigin="anonymous" referrerpolicy="no-referrer"/>
+    <link href="css/font-awesome.css" rel="stylesheet"/>
     <link href="css/custome.css" rel="stylesheet">
     <link href="css/responsive.css" rel="stylesheet">
-    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.1/animate.css"
-          integrity="sha512-K2J6Yt6ElUYEMPcTr0wm555AAyiqkgYiUgPIW18FT88/aYSNDk0EvGjsln/TEu3ee/jaHf0xoXzFppSbBtUXbQ=="
-          crossorigin="anonymous" referrerpolicy="no-referrer"/>
+    <link href="css/animate.css" rel="stylesheet"/>
+    <link href="css/fonts.css" rel="stylesheet">
     <link href="css/prism.css" rel="stylesheet">
-    <link rel="preconnect" href="https://fonts.googleapis.com">
-    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-    <link href="https://fonts.googleapis.com/css2?family=Raleway:wght@400;500;600;700&display=swap" rel="stylesheet">
+    <!-- Matomo -->
+    <script>
+        var _paq = window._paq = window._paq || [];
+        /* We explicitly disable cookie tracking to avoid privacy issues */
+        _paq.push(['disableCookies']);
+        /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
+        _paq.push(['trackPageView']);
+        _paq.push(['enableLinkTracking']);
+        (function() {
+            var u="https://analytics.apache.org/";
+            _paq.push(['setTrackerUrl', u+'matomo.php']);
+            _paq.push(['setSiteId', '27']);
+            var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
+            g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
+        })();
+    </script>
+    <!-- End Matomo Code -->
 </head>
 <body>
 <!-- header -->
@@ -58,6 +69,21 @@
                         <li class="nav-item">
                             <a class="nav-link" href="download.html">Download</a>
                         </li>
+
+                        <li class="nav-item dropdown">
+                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown4" role="button" data-bs-toggle="dropdown" aria-expanded="false">
+                                Tools
+                            </a>
+                            <ul class="dropdown-menu" aria-labelledby="navbarDropdown4">
+                                <li><a class="dropdown-item" href="providers.html">Graph Systems</a></li>
+                                <li><a class="dropdown-item" href="community.html">Languages and Tools</a></li>
+                                <li><hr class="dropdown-divider"></li>
+                                <li><a class="dropdown-item" href="https://gremlify.com/">Gremlify: Try Gremlin</a></li>
+                                <li><a class="dropdown-item" href="https://tinkerpop.apache.org/gremlint">Gremlint: Lint Gremlin</a></li>
+                                <li><a class="dropdown-item" href="https://www.gremlator.com/">Gremlator: Translate Gremlin</a></li>
+                            </ul>
+                        </li>
+
                         <li class="nav-item dropdown">
                             <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
                                data-bs-toggle="dropdown" aria-expanded="false">
@@ -80,6 +106,7 @@
                             </ul>
 
                         </li>
+
                         <li class="nav-item dropdown">
                             <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown1" role="button"
                                data-bs-toggle="dropdown" aria-expanded="false">
@@ -109,48 +136,31 @@
 
                         </li>
                         <li class="nav-item dropdown">
-                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown3" role="button"
-                               data-bs-toggle="dropdown" aria-expanded="false">
+                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown3" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                                 Community
                             </a>
                             <ul class="dropdown-menu" aria-labelledby="navbarDropdown3">
-                                <li><a class="dropdown-item" href="https://groups.google.com/group/gremlin-users">User
-                                    Mailing List</a></li>
-                                <li><a class="dropdown-item"
-                                       href="https://lists.apache.org/list.html?dev@tinkerpop.apache.org">Developer
-                                    Mailing List</a></li>
-                                <li><a class="dropdown-item" href="https://discord.gg/ndMpKZcBEE" target="_blank"><img
-                                        src="img/discord_logo.png" class="nav-icon">Join us on Discord</a></li>
-                                <li><a class="dropdown-item" href="https://issues.apache.org/jira/browse/TINKERPOP/">Issue
-                                    Tracker</a></li>
-                                <li><a class="dropdown-item"
-                                       href="https://tinkerpop.apache.org/docs/current/dev/developer/#_contributing">Contributing</a>
-                                </li>
-                                <li><a class="dropdown-item" href="providers.html">Data System Support</a></li>
-                                <li><a class="dropdown-item" href="community.html">Languages and Tools</a></li>
-                                <li><a class="dropdown-item"
-                                       href="https://tinkerpop.apache.org/docs/current/dev/provider/#policies">Policies</a>
-                                </li>
-                                <li>
-                                    <hr class="dropdown-divider">
-                                </li>
-                                <li><a class="dropdown-item" href="https://github.com/apache/tinkerpop/"><img
-                                        src="img/github-logo.png" class="nav-icon">GitHub</a></li>
-                                <li><a class="dropdown-item" href="https://twitter.com/apachetinkerpop"><img
-                                        src="img/twitter-logo.png" class="nav-icon">Twitter</a></li>
+                                <li><a class="dropdown-item" href="https://discord.gg/kfebyvDM9H" target="_blank"><img src="img/discord-logo.png" class="nav-icon"/>Discord</a></li>
+                                <li><a class="dropdown-item" href="https://www.answeroverflow.com/c/838910279550238720"><img src="img/answer-overflow-logo.png" class="nav-icon"/>Answer Overflow</a></li>
+                                <li><a class="dropdown-item" href="https://stackoverflow.com/questions/tagged/gremlin"><img src="img/stack-overflow-logo.png" class="nav-icon"/>Stack Overflow</a></li>
+                                <li><a class="dropdown-item" href="https://groups.google.com/group/gremlin-users"><img src="img/mail.png" class="nav-icon"/>User Mailing List</a></li>
+                                <li><a class="dropdown-item" href="https://lists.apache.org/list.html?dev@tinkerpop.apache.org"><img src="img/mail.png" class="nav-icon"/>Developer Mailing List</a></li>
+                                <li><a class="dropdown-item" href="https://issues.apache.org/jira/browse/TINKERPOP/"><img src="img/jira-logo.png" class="nav-icon"/>Issue Tracker</a></li>
+                                <li><a class="dropdown-item" href="https://github.com/apache/tinkerpop/"><img src="img/github-logo.png" class="nav-icon"/>GitHub</a></li>
+                                <li><a class="dropdown-item" href="https://www.twitch.tv/apachetinkerpop"><img src="img/twitch-logo.png" class="nav-icon"/>Twitch</a></li>
+                                <li><a class="dropdown-item" href="https://twitter.com/apachetinkerpop"><img src="img/twitter-logo.png" class="nav-icon"/>Twitter</a></li>
+                                <li><a class="dropdown-item" href="https://www.youtube.com/@apachetinkerpop"><img src="img/youtube-logo.png" class="nav-icon"/>YouTube</a></li>
+                                <li><hr class="dropdown-divider"></li>
+                                <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/dev/developer/#_contributing">Contributing</a></li>
+                                <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/dev/provider/#policies">Policies</a></li>
                             </ul>
-
-                        </li>
-
-                        <li class="nav-item">
-                            <a class="nav-link" href="https://tinkerpop.apache.org/gremlint/">Gremlint</a>
                         </li>
                         <li class="nav-item dropdown">
-                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown4" role="button"
+                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown5" role="button"
                                data-bs-toggle="dropdown" aria-expanded="false">
                                 Apache Software
                             </a>
-                            <ul class="dropdown-menu" aria-labelledby="navbarDropdown4">
+                            <ul class="dropdown-menu" aria-labelledby="navbarDropdown5">
                                 <li><a class="dropdown-item" href="https://www.apache.org/">Apache Homepage</a></li>
                                 <li><a class="dropdown-item" href="https://www.apache.org/licenses/">License</a></li>
                                 <li><a class="dropdown-item"
@@ -237,8 +247,8 @@
 
 
                     <!-- clojure -->
-                    <div class="accordion-item">
-                        <h2 class="accordion-header" id="headingOne">
+                    <div class="accordion-item" id="lang-clojure">
+                        <h2 class="accordion-header">
                             <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
                                     data-bs-target="#collapseOne" aria-expanded="false" aria-controls="collapseOne">
                                 <img src="img/community/clojure.png" class="img-fluid me-3" alt="img">Clojure
@@ -271,8 +281,8 @@
                     </div>
 
                     <!-- elixer -->
-                    <div class="accordion-item">
-                        <h2 class="accordion-header" id="headingTwo">
+                    <div class="accordion-item" id="lang-elixer">
+                        <h2 class="accordion-header" >
                             <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
                                     data-bs-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
                                 <img src="img/community/elixer.png" class="img-fluid me-3" alt="img">Elixer
@@ -302,8 +312,8 @@
                     </div>
 
                     <!-- go -->
-                    <div class="accordion-item">
-                        <h2 class="accordion-header" id="heading3">
+                    <div class="accordion-item" id="lang-go">
+                        <h2 class="accordion-header">
                             <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
                                     data-bs-target="#collapse3" aria-expanded="false" aria-controls="collapse3">
                                 <img src="img/community/go.png" class="img-fluid me-3" alt="img">Go
@@ -338,7 +348,7 @@
                                             </div>
                                             <div class="col-md-12 mb-4 mb-lg-0 col-lg-6 text-center">
                                                 <div class="code-box">
-                                                    <code class="language-go-module">COMING SOON</code>
+                                                    <code class="language-go-module">go get github.com/apache/tinkerpop/gremlin-go/v3&#64;v3.6.4</code>
                                                 </div>
                                                 <p class="medium black">Go Module</p>
                                             </div>
@@ -347,7 +357,7 @@
                                   </div>
 
                                   <div class="mt-4 text-center text-blue ft-17">
-                                      <a href="https://github.com/apache/tinkerpop/blob/master/gremlin-go/README.md"
+                                      <a href="https://tinkerpop.apache.org/docs/current/reference/#gremlin-go"
                                          target="_blank"><u>Learn More</u></a>
                                   </div>
 
@@ -375,8 +385,8 @@
                     </div>
 
                     <!-- groovy -->
-                    <div class="accordion-item">
-                        <h2 class="accordion-header" id="heading4">
+                    <div class="accordion-item" id="lang-groovy">
+                        <h2 class="accordion-header">
                             <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
                                     data-bs-target="#collapse4" aria-expanded="false" aria-controls="collapse4">
                                 <img src="img/community/groovy.png" class="img-fluid me-3" alt="img">Groovy
@@ -410,7 +420,7 @@
                                             <div class="col-md-12 mb-4 mb-lg-0 col-lg-6 text-center">
                                                 <div class="code-box">
                                                     <code class="language-groovy">implementation
-                                                        'org.apache.tinkerpop:gremlin-groovy:3.6.0'</code>
+                                                        'org.apache.tinkerpop:gremlin-groovy:3.6.4'</code>
                                                 </div>
                                                 <p class="medium black">Gradle</p>
                                             </div>
@@ -428,8 +438,8 @@
                     </div>
 
                     <!-- haskell -->
-                    <div class="accordion-item">
-                        <h2 class="accordion-header" id="heading5">
+                    <div class="accordion-item" id="lang-haskell">
+                        <h2 class="accordion-header">
                             <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
                                     data-bs-target="#collapse5" aria-expanded="false" aria-controls="collapse5">
                                 <img src="img/community/haskell.png" class="img-fluid me-3" alt="img">Haskell
@@ -459,8 +469,8 @@
                     </div>
 
                     <!-- java -->
-                    <div class="accordion-item">
-                        <h2 class="accordion-header" id="heading6">
+                    <div class="accordion-item" id="lang-java">
+                        <h2 class="accordion-header">
                             <button class="accordion-button " type="button" data-bs-toggle="collapse"
                                     data-bs-target="#collapse6" aria-expanded="true" aria-controls="collapse6">
                                 <img src="img/community/java.png" class="img-fluid me-3" alt="img">Java
@@ -470,7 +480,7 @@
                                         src="img/community/tool.png" class="img-fluid " alt="img"></div>
                             </button>
                         </h2>
-                        <div id="collapse6" class="accordion-collapse collapse show" aria-labelledby="heading6"
+                        <div id="collapse6" class="accordion-collapse collapse" aria-labelledby="heading6"
                              data-bs-parent="#accordionExample">
                             <div class="accordion-body">
                                 <div class="d-flex align-items-start">
@@ -498,7 +508,7 @@
 &lt;dependency&gt;
   &lt;groupId&gt;org.apache.tinkerpop&lt;/groupId&gt;
   &lt;artifactId&gt;gremlin-driver&lt;/artifactId&gt;
-  &lt;version&gt;3.6.0&lt;/version&gt;
+  &lt;version&gt;3.6.4&lt;/version&gt;
 &lt;/dependency&gt;</code></pre>
                                                 </div>
                                                 <p class="medium black">Maven</p>
@@ -521,7 +531,10 @@
                                         <p class="ft-17 mb-2">
                                             Third-Party Libraries and Tools
                                         </p>
-                                        <p class="ft-17">- <a class="text-blue" href="http://syncleus.com/Ferma/"
+                                        <p class="ft-17">- <a class="text-blue" href="https://github.com/eclipse/jnosql"
+                                                              target="_blank">Eclipse JNoSQL</a>: An Object Graph Mapper (OGM)
+                                            for Apache TinkerPop.
+                                            <br>- <a class="text-blue" href="http://syncleus.com/Ferma/"
                                                               target="_blank">Ferma</a>: An Object Graph Mapper (OGM)
                                             for Apache TinkerPop.
                                             <br>- <a class="text-blue" href="https://github.com/karthicks/gremlin-ogm"
@@ -542,8 +555,8 @@
                     </div>
 
                     <!-- javascript -->
-                    <div class="accordion-item">
-                        <h2 class="accordion-header" id="heading7">
+                    <div class="accordion-item" id="lang-javascript">
+                        <h2 class="accordion-header">
                             <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
                                     data-bs-target="#collapse7" aria-expanded="false" aria-controls="collapse7">
                                 <img src="img/community/javascript.png" class="img-fluid me-3" alt="img">Javascript
@@ -626,8 +639,8 @@
                     </div>
 
                     <!-- kotlin -->
-                    <div class="accordion-item">
-                        <h2 class="accordion-header" id="heading8">
+                    <div class="accordion-item" id="lang-kotlin">
+                        <h2 class="accordion-header">
                             <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
                                     data-bs-target="#collapse8" aria-expanded="false" aria-controls="collapse8">
                                 <img src="img/community/kotlin.png" class="img-fluid me-3" alt="img">Kotlin
@@ -658,8 +671,8 @@
 
 
                     <!-- c# -->
-                    <div class="accordion-item">
-                        <h2 class="accordion-header" id="heading9">
+                    <div class="accordion-item" id="lang-csharp">
+                        <h2 class="accordion-header">
                             <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
                                     data-bs-target="#collapse9" aria-expanded="false" aria-controls="collapse9">
                                 <img src="img/community/c-sharp-logo-png.png" class="img-fluid me-3" alt="img">.NET
@@ -690,7 +703,7 @@
                                             </div>
                                             <div class="col-md-12 mb-4 mb-lg-0 col-lg-6 text-center">
                                                 <div class="code-box">
-                                                    <pre><code class="language-plain">dotnet add package Gremlin.Net --version 3.6.0</code></pre>
+                                                    <pre><code class="language-plain">dotnet add package Gremlin.Net --version 3.6.4</code></pre>
                                                 </div>
                                                 <p class="medium black">NuGet</p>
                                             </div>
@@ -723,8 +736,8 @@
                     </div>
 
                     <!-- python -->
-                    <div class="accordion-item">
-                        <h2 class="accordion-header" id="heading10">
+                    <div class="accordion-item" id="lang-python">
+                        <h2 class="accordion-header">
                             <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
                                     data-bs-target="#collapse10" aria-expanded="false" aria-controls="collapse10">
                                 <img src="img/community/python.png" class="img-fluid me-3" alt="img">Python
@@ -809,8 +822,8 @@
                     </div>
 
                     <!-- php -->
-                    <div class="accordion-item">
-                        <h2 class="accordion-header" id="heading11">
+                    <div class="accordion-item" id="lang-php">
+                        <h2 class="accordion-header">
                             <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
                                     data-bs-target="#collapse11" aria-expanded="false" aria-controls="collapse11">
                                 <img src="img/community/php.png" class="img-fluid me-3" alt="img">PHP
@@ -840,8 +853,8 @@
                     </div>
 
                     <!-- ruby -->
-                    <div class="accordion-item">
-                        <h2 class="accordion-header" id="heading12">
+                    <div class="accordion-item" id="lang-ruby">
+                        <h2 class="accordion-header">
                             <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
                                     data-bs-target="#collapse12" aria-expanded="false" aria-controls="collapse12">
                                 <img src="img/community/ruby.png" class="img-fluid me-3" alt="img">Ruby
@@ -876,8 +889,8 @@
 
 
                     <!-- rust -->
-                    <div class="accordion-item">
-                        <h2 class="accordion-header" id="heading13">
+                    <div class="accordion-item" id="lang-rust">
+                        <h2 class="accordion-header">
                             <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
                                     data-bs-target="#collapse13" aria-expanded="false" aria-controls="collapse13">
                                 <img src="img/community/rust.png" class="img-fluid me-3" alt="img">Rust
@@ -908,8 +921,8 @@
                 </div>
 
                 <!-- scala -->
-                <div class="accordion-item">
-                    <h2 class="accordion-header" id="heading14">
+                <div class="accordion-item" id="lang-scala">
+                    <h2 class="accordion-header">
                         <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
                                 data-bs-target="#collapse14" aria-expanded="false" aria-controls="collapse14">
                             <img src="img/community/scala.png" class="img-fluid me-3" alt="img">Scala
@@ -946,11 +959,12 @@
                         </div>
                     </div>
                 </div>
+
                 <h2 class="ft-25 black bold mt-5 mb-4">Docker</h2>
 
                 <!-- docker -->
-                <div class="accordion-item">
-                    <h2 class="accordion-header" id="heading15">
+                <div class="accordion-item" id="docker">
+                    <h2 class="accordion-header">
                         <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
                                 data-bs-target="#collapse15" aria-expanded="false" aria-controls="collapse15">
                             <img src="img/community/docker.png" class="img-fluid me-3" alt="img">Docker
@@ -996,8 +1010,9 @@
 
                 <!-- compilers/transpilers -->
                 <h2 class="ft-25 black bold mt-5 mb-4">Compilers and Transpilers</h2>
-                <div class="accordion-item">
-                    <h2 class="accordion-header" id="heading16">
+
+                <div class="accordion-item" id="pilers">
+                    <h2 class="accordion-header">
                         <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
                                 data-bs-target="#collapse16" aria-expanded="false" aria-controls="collapse16">
                             <img src="img/community/compiler.png" class="img-fluid me-3" alt="img">Compilers and
@@ -1038,8 +1053,9 @@
 
                 <!-- poweredby -->
                 <h2 class="ft-25 black bold mt-5 mb-4">Powered By</h2>
-                <div class="accordion-item">
-                    <h2 class="accordion-header" id="heading17">
+
+                <div class="accordion-item" id="powered-by">
+                    <h2 class="accordion-header">
                         <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
                                 data-bs-target="#collapse17" aria-expanded="false" aria-controls="collapse17">
                             <img src="img/community/powered-by.png" class="img-fluid me-3" alt="img">Powered By
@@ -1077,6 +1093,9 @@
                                         <br>- <a class="text-blue" href="https://github.com/bechbd/gremlin-ide"
                                                  target="_blank">gremlin-ide</a>: An IDE for Apache TinkerPop-enabled
                                         databases using React and Electron.
+                                        <br>- <a class="text-blue" href="https://www.gremlator.com/"
+                                                 target="_blank">Gremlator</a>: A helpful tool that translates Gremlin
+                                        written in one programming language to the format of another.
                                         <br>- <a class="text-blue" href="https://gremlify.com/"
                                                  target="_blank">gremlify</a>: A Gremlin workspace for queries and
                                         visualization.
@@ -1137,9 +1156,9 @@
         <div class="row d-flex justify-content-center">
             <div class="col-md-8 col-lg-6">
                 <div class="ju-box">
-                    <h2 class="ft-40 text-blue bold">Join Us on</h2>
-                    <p class="bold">Join us on our Discord Chat</p>
-                    <a href="https://discord.gg/ndMpKZcBEE"><img src="img/tpvewx.png" class="img-fluid mt-3" alt="img"></a>
+                    <h2 class="ft-40 text-blue bold">Join Us</h2>
+                    <p class="bold">Join us on our Discord Server</p>
+                    <a href="https://discord.gg/kfebyvDM9H"><img src="img/tpvewx.png" class="img-fluid mt-3" alt="img"></a>
                 </div>
             </div>
         </div>
@@ -1153,15 +1172,13 @@
             <div class="row">
                 <div class="col-md-4">
                     <div class="bold ft-25">Apache TinkerPop™</div>
-                    <p class="mt-2 mb-4">Apache TinkerPop™ is a graph computing framework for both graph databases
-                        (OLTP) and graph analytic systems (OLAP).</p>
+                    <p class="mt-2 mb-4">Apache TinkerPop™ is a graph computing framework for both graph databases (OLTP) and graph analytic systems (OLAP).</p>
                     <ul class="list-unstyled list-inline hover-op-low">
-                        <li class="list-inline-item"><a href="https://discord.gg/ndMpKZcBEE"><img
-                                src="img/social/discord.svg" class="img-fluid" alt="img"></a></li>
-                        <li class="list-inline-item"><a href="https://twitter.com/apachetinkerpop"><img
-                                src="img/social/twitter-square.svg" class="img-fluid" alt="img"></a></li>
-                        <li class="list-inline-item"><a href="https://github.com/apache/tinkerpop"><img
-                                src="img/social/github-box.svg" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://discord.gg/kfebyvDM9H"><img src="img/social/discord.svg" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://github.com/apache/tinkerpop"><img src="img/social/github-box.svg" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://www.twitch.tv/apachetinkerpop"><img src="img/social/twitch.png" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://twitter.com/apachetinkerpop"><img src="img/social/twitter-square.svg" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://www.youtube.com/@apachetinkerpop"><img src="img/social/youtube.png" class="img-fluid" alt="img"></a></li>
                     </ul>
                 </div>
                 <div class="col-md-4 ft-links">
@@ -1172,6 +1189,7 @@
                                 <li><a href="index.html">Home</a></li>
                                 <li><a href="download.html">Downloads</a></li>
                                 <li><a href="https://tinkerpop.apache.org/docs/current">Documentation</a></li>
+                                <li><a href="https://privacy.apache.org/policies/privacy-policy-public.html" target="_blank">Privacy Policy</a></li>
                             </ul>
                         </div>
                         <div class="col-lg-6">
@@ -1196,7 +1214,7 @@
         <div class="container">
             <div class="row">
                 <div class="col-12">
-                    Copyright © 2015-2022 The Apache Software Foundation
+                    Copyright © 2015-2023 The Apache Software Foundation
                 </div>
             </div>
         </div>
@@ -1204,10 +1222,14 @@
 </footer>
 <script src="js/jquery-1.11.1.js"></script>
 <script src="js/bootstrap.bundle.min.js"></script>
-<script src="https://cdnjs.cloudflare.com/ajax/libs/wow/1.1.2/wow.min.js"
-        integrity="sha512-Eak/29OTpb36LLo2r47IpVzPBLXnAMPAVypbSZiZ4Qkf8p/7S/XRG5xp7OKWPPYfJT6metI+IORkR5G8F900+g=="
-        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
+<script src="js/wow.min.js"></script>
 <script src="js/my.js"></script>
 <script src="js/prism.js"></script>
+<script>
+    jQuery(document).ready(function($) {
+        const hash = window.location.hash;
+        if (hash) $(hash + " > h2 > button.accordion-button").click();
+    });
+</script>
 </body>
 </html>
diff --git a/docs/site/home/css/animate.css b/docs/site/home/css/animate.css
new file mode 100644
index 0000000..188e78f
--- /dev/null
+++ b/docs/site/home/css/animate.css
@@ -0,0 +1,3340 @@
+@charset "UTF-8";
+
+/*!
+ * animate.css -http://daneden.me/animate
+ * Version - 3.5.0
+ * Licensed under the MIT license - http://opensource.org/licenses/MIT
+ *
+ * Copyright (c) 2016 Daniel Eden
+ */
+
+.animated {
+  -webkit-animation-duration: 1s;
+  animation-duration: 1s;
+  -webkit-animation-fill-mode: both;
+  animation-fill-mode: both;
+}
+
+.animated.infinite {
+  -webkit-animation-iteration-count: infinite;
+  animation-iteration-count: infinite;
+}
+
+.animated.hinge {
+  -webkit-animation-duration: 2s;
+  animation-duration: 2s;
+}
+
+.animated.flipOutX,
+.animated.flipOutY,
+.animated.bounceIn,
+.animated.bounceOut {
+  -webkit-animation-duration: .75s;
+  animation-duration: .75s;
+}
+
+@-webkit-keyframes bounce {
+  from, 20%, 53%, 80%, to {
+    -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+    -webkit-transform: translate3d(0,0,0);
+    transform: translate3d(0,0,0);
+  }
+
+  40%, 43% {
+    -webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
+    animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
+    -webkit-transform: translate3d(0, -30px, 0);
+    transform: translate3d(0, -30px, 0);
+  }
+
+  70% {
+    -webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
+    animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
+    -webkit-transform: translate3d(0, -15px, 0);
+    transform: translate3d(0, -15px, 0);
+  }
+
+  90% {
+    -webkit-transform: translate3d(0,-4px,0);
+    transform: translate3d(0,-4px,0);
+  }
+}
+
+@keyframes bounce {
+  from, 20%, 53%, 80%, to {
+    -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+    -webkit-transform: translate3d(0,0,0);
+    transform: translate3d(0,0,0);
+  }
+
+  40%, 43% {
+    -webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
+    animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
+    -webkit-transform: translate3d(0, -30px, 0);
+    transform: translate3d(0, -30px, 0);
+  }
+
+  70% {
+    -webkit-animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
+    animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
+    -webkit-transform: translate3d(0, -15px, 0);
+    transform: translate3d(0, -15px, 0);
+  }
+
+  90% {
+    -webkit-transform: translate3d(0,-4px,0);
+    transform: translate3d(0,-4px,0);
+  }
+}
+
+.bounce {
+  -webkit-animation-name: bounce;
+  animation-name: bounce;
+  -webkit-transform-origin: center bottom;
+  transform-origin: center bottom;
+}
+
+@-webkit-keyframes flash {
+  from, 50%, to {
+    opacity: 1;
+  }
+
+  25%, 75% {
+    opacity: 0;
+  }
+}
+
+@keyframes flash {
+  from, 50%, to {
+    opacity: 1;
+  }
+
+  25%, 75% {
+    opacity: 0;
+  }
+}
+
+.flash {
+  -webkit-animation-name: flash;
+  animation-name: flash;
+}
+
+/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
+
+@-webkit-keyframes pulse {
+  from {
+    -webkit-transform: scale3d(1, 1, 1);
+    transform: scale3d(1, 1, 1);
+  }
+
+  50% {
+    -webkit-transform: scale3d(1.05, 1.05, 1.05);
+    transform: scale3d(1.05, 1.05, 1.05);
+  }
+
+  to {
+    -webkit-transform: scale3d(1, 1, 1);
+    transform: scale3d(1, 1, 1);
+  }
+}
+
+@keyframes pulse {
+  from {
+    -webkit-transform: scale3d(1, 1, 1);
+    transform: scale3d(1, 1, 1);
+  }
+
+  50% {
+    -webkit-transform: scale3d(1.05, 1.05, 1.05);
+    transform: scale3d(1.05, 1.05, 1.05);
+  }
+
+  to {
+    -webkit-transform: scale3d(1, 1, 1);
+    transform: scale3d(1, 1, 1);
+  }
+}
+
+.pulse {
+  -webkit-animation-name: pulse;
+  animation-name: pulse;
+}
+
+@-webkit-keyframes rubberBand {
+  from {
+    -webkit-transform: scale3d(1, 1, 1);
+    transform: scale3d(1, 1, 1);
+  }
+
+  30% {
+    -webkit-transform: scale3d(1.25, 0.75, 1);
+    transform: scale3d(1.25, 0.75, 1);
+  }
+
+  40% {
+    -webkit-transform: scale3d(0.75, 1.25, 1);
+    transform: scale3d(0.75, 1.25, 1);
+  }
+
+  50% {
+    -webkit-transform: scale3d(1.15, 0.85, 1);
+    transform: scale3d(1.15, 0.85, 1);
+  }
+
+  65% {
+    -webkit-transform: scale3d(.95, 1.05, 1);
+    transform: scale3d(.95, 1.05, 1);
+  }
+
+  75% {
+    -webkit-transform: scale3d(1.05, .95, 1);
+    transform: scale3d(1.05, .95, 1);
+  }
+
+  to {
+    -webkit-transform: scale3d(1, 1, 1);
+    transform: scale3d(1, 1, 1);
+  }
+}
+
+@keyframes rubberBand {
+  from {
+    -webkit-transform: scale3d(1, 1, 1);
+    transform: scale3d(1, 1, 1);
+  }
+
+  30% {
+    -webkit-transform: scale3d(1.25, 0.75, 1);
+    transform: scale3d(1.25, 0.75, 1);
+  }
+
+  40% {
+    -webkit-transform: scale3d(0.75, 1.25, 1);
+    transform: scale3d(0.75, 1.25, 1);
+  }
+
+  50% {
+    -webkit-transform: scale3d(1.15, 0.85, 1);
+    transform: scale3d(1.15, 0.85, 1);
+  }
+
+  65% {
+    -webkit-transform: scale3d(.95, 1.05, 1);
+    transform: scale3d(.95, 1.05, 1);
+  }
+
+  75% {
+    -webkit-transform: scale3d(1.05, .95, 1);
+    transform: scale3d(1.05, .95, 1);
+  }
+
+  to {
+    -webkit-transform: scale3d(1, 1, 1);
+    transform: scale3d(1, 1, 1);
+  }
+}
+
+.rubberBand {
+  -webkit-animation-name: rubberBand;
+  animation-name: rubberBand;
+}
+
+@-webkit-keyframes shake {
+  from, to {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+
+  10%, 30%, 50%, 70%, 90% {
+    -webkit-transform: translate3d(-10px, 0, 0);
+    transform: translate3d(-10px, 0, 0);
+  }
+
+  20%, 40%, 60%, 80% {
+    -webkit-transform: translate3d(10px, 0, 0);
+    transform: translate3d(10px, 0, 0);
+  }
+}
+
+@keyframes shake {
+  from, to {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+
+  10%, 30%, 50%, 70%, 90% {
+    -webkit-transform: translate3d(-10px, 0, 0);
+    transform: translate3d(-10px, 0, 0);
+  }
+
+  20%, 40%, 60%, 80% {
+    -webkit-transform: translate3d(10px, 0, 0);
+    transform: translate3d(10px, 0, 0);
+  }
+}
+
+.shake {
+  -webkit-animation-name: shake;
+  animation-name: shake;
+}
+
+@-webkit-keyframes headShake {
+  0% {
+    -webkit-transform: translateX(0);
+    transform: translateX(0);
+  }
+
+  6.5% {
+    -webkit-transform: translateX(-6px) rotateY(-9deg);
+    transform: translateX(-6px) rotateY(-9deg);
+  }
+
+  18.5% {
+    -webkit-transform: translateX(5px) rotateY(7deg);
+    transform: translateX(5px) rotateY(7deg);
+  }
+
+  31.5% {
+    -webkit-transform: translateX(-3px) rotateY(-5deg);
+    transform: translateX(-3px) rotateY(-5deg);
+  }
+
+  43.5% {
+    -webkit-transform: translateX(2px) rotateY(3deg);
+    transform: translateX(2px) rotateY(3deg);
+  }
+
+  50% {
+    -webkit-transform: translateX(0);
+    transform: translateX(0);
+  }
+}
+
+@keyframes headShake {
+  0% {
+    -webkit-transform: translateX(0);
+    transform: translateX(0);
+  }
+
+  6.5% {
+    -webkit-transform: translateX(-6px) rotateY(-9deg);
+    transform: translateX(-6px) rotateY(-9deg);
+  }
+
+  18.5% {
+    -webkit-transform: translateX(5px) rotateY(7deg);
+    transform: translateX(5px) rotateY(7deg);
+  }
+
+  31.5% {
+    -webkit-transform: translateX(-3px) rotateY(-5deg);
+    transform: translateX(-3px) rotateY(-5deg);
+  }
+
+  43.5% {
+    -webkit-transform: translateX(2px) rotateY(3deg);
+    transform: translateX(2px) rotateY(3deg);
+  }
+
+  50% {
+    -webkit-transform: translateX(0);
+    transform: translateX(0);
+  }
+}
+
+.headShake {
+  -webkit-animation-timing-function: ease-in-out;
+  animation-timing-function: ease-in-out;
+  -webkit-animation-name: headShake;
+  animation-name: headShake;
+}
+
+@-webkit-keyframes swing {
+  20% {
+    -webkit-transform: rotate3d(0, 0, 1, 15deg);
+    transform: rotate3d(0, 0, 1, 15deg);
+  }
+
+  40% {
+    -webkit-transform: rotate3d(0, 0, 1, -10deg);
+    transform: rotate3d(0, 0, 1, -10deg);
+  }
+
+  60% {
+    -webkit-transform: rotate3d(0, 0, 1, 5deg);
+    transform: rotate3d(0, 0, 1, 5deg);
+  }
+
+  80% {
+    -webkit-transform: rotate3d(0, 0, 1, -5deg);
+    transform: rotate3d(0, 0, 1, -5deg);
+  }
+
+  to {
+    -webkit-transform: rotate3d(0, 0, 1, 0deg);
+    transform: rotate3d(0, 0, 1, 0deg);
+  }
+}
+
+@keyframes swing {
+  20% {
+    -webkit-transform: rotate3d(0, 0, 1, 15deg);
+    transform: rotate3d(0, 0, 1, 15deg);
+  }
+
+  40% {
+    -webkit-transform: rotate3d(0, 0, 1, -10deg);
+    transform: rotate3d(0, 0, 1, -10deg);
+  }
+
+  60% {
+    -webkit-transform: rotate3d(0, 0, 1, 5deg);
+    transform: rotate3d(0, 0, 1, 5deg);
+  }
+
+  80% {
+    -webkit-transform: rotate3d(0, 0, 1, -5deg);
+    transform: rotate3d(0, 0, 1, -5deg);
+  }
+
+  to {
+    -webkit-transform: rotate3d(0, 0, 1, 0deg);
+    transform: rotate3d(0, 0, 1, 0deg);
+  }
+}
+
+.swing {
+  -webkit-transform-origin: top center;
+  transform-origin: top center;
+  -webkit-animation-name: swing;
+  animation-name: swing;
+}
+
+@-webkit-keyframes tada {
+  from {
+    -webkit-transform: scale3d(1, 1, 1);
+    transform: scale3d(1, 1, 1);
+  }
+
+  10%, 20% {
+    -webkit-transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
+    transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
+  }
+
+  30%, 50%, 70%, 90% {
+    -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
+    transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
+  }
+
+  40%, 60%, 80% {
+    -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
+    transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
+  }
+
+  to {
+    -webkit-transform: scale3d(1, 1, 1);
+    transform: scale3d(1, 1, 1);
+  }
+}
+
+@keyframes tada {
+  from {
+    -webkit-transform: scale3d(1, 1, 1);
+    transform: scale3d(1, 1, 1);
+  }
+
+  10%, 20% {
+    -webkit-transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
+    transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
+  }
+
+  30%, 50%, 70%, 90% {
+    -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
+    transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
+  }
+
+  40%, 60%, 80% {
+    -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
+    transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
+  }
+
+  to {
+    -webkit-transform: scale3d(1, 1, 1);
+    transform: scale3d(1, 1, 1);
+  }
+}
+
+.tada {
+  -webkit-animation-name: tada;
+  animation-name: tada;
+}
+
+/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
+
+@-webkit-keyframes wobble {
+  from {
+    -webkit-transform: none;
+    transform: none;
+  }
+
+  15% {
+    -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
+    transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
+  }
+
+  30% {
+    -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
+    transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
+  }
+
+  45% {
+    -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
+    transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
+  }
+
+  60% {
+    -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
+    transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
+  }
+
+  75% {
+    -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
+    transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
+  }
+
+  to {
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+@keyframes wobble {
+  from {
+    -webkit-transform: none;
+    transform: none;
+  }
+
+  15% {
+    -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
+    transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
+  }
+
+  30% {
+    -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
+    transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
+  }
+
+  45% {
+    -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
+    transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
+  }
+
+  60% {
+    -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
+    transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
+  }
+
+  75% {
+    -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
+    transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
+  }
+
+  to {
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+.wobble {
+  -webkit-animation-name: wobble;
+  animation-name: wobble;
+}
+
+@-webkit-keyframes jello {
+  from, 11.1%, to {
+    -webkit-transform: none;
+    transform: none;
+  }
+
+  22.2% {
+    -webkit-transform: skewX(-12.5deg) skewY(-12.5deg);
+    transform: skewX(-12.5deg) skewY(-12.5deg);
+  }
+
+  33.3% {
+    -webkit-transform: skewX(6.25deg) skewY(6.25deg);
+    transform: skewX(6.25deg) skewY(6.25deg);
+  }
+
+  44.4% {
+    -webkit-transform: skewX(-3.125deg) skewY(-3.125deg);
+    transform: skewX(-3.125deg) skewY(-3.125deg);
+  }
+
+  55.5% {
+    -webkit-transform: skewX(1.5625deg) skewY(1.5625deg);
+    transform: skewX(1.5625deg) skewY(1.5625deg);
+  }
+
+  66.6% {
+    -webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg);
+    transform: skewX(-0.78125deg) skewY(-0.78125deg);
+  }
+
+  77.7% {
+    -webkit-transform: skewX(0.390625deg) skewY(0.390625deg);
+    transform: skewX(0.390625deg) skewY(0.390625deg);
+  }
+
+  88.8% {
+    -webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
+    transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
+  }
+}
+
+@keyframes jello {
+  from, 11.1%, to {
+    -webkit-transform: none;
+    transform: none;
+  }
+
+  22.2% {
+    -webkit-transform: skewX(-12.5deg) skewY(-12.5deg);
+    transform: skewX(-12.5deg) skewY(-12.5deg);
+  }
+
+  33.3% {
+    -webkit-transform: skewX(6.25deg) skewY(6.25deg);
+    transform: skewX(6.25deg) skewY(6.25deg);
+  }
+
+  44.4% {
+    -webkit-transform: skewX(-3.125deg) skewY(-3.125deg);
+    transform: skewX(-3.125deg) skewY(-3.125deg);
+  }
+
+  55.5% {
+    -webkit-transform: skewX(1.5625deg) skewY(1.5625deg);
+    transform: skewX(1.5625deg) skewY(1.5625deg);
+  }
+
+  66.6% {
+    -webkit-transform: skewX(-0.78125deg) skewY(-0.78125deg);
+    transform: skewX(-0.78125deg) skewY(-0.78125deg);
+  }
+
+  77.7% {
+    -webkit-transform: skewX(0.390625deg) skewY(0.390625deg);
+    transform: skewX(0.390625deg) skewY(0.390625deg);
+  }
+
+  88.8% {
+    -webkit-transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
+    transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
+  }
+}
+
+.jello {
+  -webkit-animation-name: jello;
+  animation-name: jello;
+  -webkit-transform-origin: center;
+  transform-origin: center;
+}
+
+@-webkit-keyframes bounceIn {
+  from, 20%, 40%, 60%, 80%, to {
+    -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+  }
+
+  0% {
+    opacity: 0;
+    -webkit-transform: scale3d(.3, .3, .3);
+    transform: scale3d(.3, .3, .3);
+  }
+
+  20% {
+    -webkit-transform: scale3d(1.1, 1.1, 1.1);
+    transform: scale3d(1.1, 1.1, 1.1);
+  }
+
+  40% {
+    -webkit-transform: scale3d(.9, .9, .9);
+    transform: scale3d(.9, .9, .9);
+  }
+
+  60% {
+    opacity: 1;
+    -webkit-transform: scale3d(1.03, 1.03, 1.03);
+    transform: scale3d(1.03, 1.03, 1.03);
+  }
+
+  80% {
+    -webkit-transform: scale3d(.97, .97, .97);
+    transform: scale3d(.97, .97, .97);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: scale3d(1, 1, 1);
+    transform: scale3d(1, 1, 1);
+  }
+}
+
+@keyframes bounceIn {
+  from, 20%, 40%, 60%, 80%, to {
+    -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+  }
+
+  0% {
+    opacity: 0;
+    -webkit-transform: scale3d(.3, .3, .3);
+    transform: scale3d(.3, .3, .3);
+  }
+
+  20% {
+    -webkit-transform: scale3d(1.1, 1.1, 1.1);
+    transform: scale3d(1.1, 1.1, 1.1);
+  }
+
+  40% {
+    -webkit-transform: scale3d(.9, .9, .9);
+    transform: scale3d(.9, .9, .9);
+  }
+
+  60% {
+    opacity: 1;
+    -webkit-transform: scale3d(1.03, 1.03, 1.03);
+    transform: scale3d(1.03, 1.03, 1.03);
+  }
+
+  80% {
+    -webkit-transform: scale3d(.97, .97, .97);
+    transform: scale3d(.97, .97, .97);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: scale3d(1, 1, 1);
+    transform: scale3d(1, 1, 1);
+  }
+}
+
+.bounceIn {
+  -webkit-animation-name: bounceIn;
+  animation-name: bounceIn;
+}
+
+@-webkit-keyframes bounceInDown {
+  from, 60%, 75%, 90%, to {
+    -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+  }
+
+  0% {
+    opacity: 0;
+    -webkit-transform: translate3d(0, -3000px, 0);
+    transform: translate3d(0, -3000px, 0);
+  }
+
+  60% {
+    opacity: 1;
+    -webkit-transform: translate3d(0, 25px, 0);
+    transform: translate3d(0, 25px, 0);
+  }
+
+  75% {
+    -webkit-transform: translate3d(0, -10px, 0);
+    transform: translate3d(0, -10px, 0);
+  }
+
+  90% {
+    -webkit-transform: translate3d(0, 5px, 0);
+    transform: translate3d(0, 5px, 0);
+  }
+
+  to {
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+@keyframes bounceInDown {
+  from, 60%, 75%, 90%, to {
+    -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+  }
+
+  0% {
+    opacity: 0;
+    -webkit-transform: translate3d(0, -3000px, 0);
+    transform: translate3d(0, -3000px, 0);
+  }
+
+  60% {
+    opacity: 1;
+    -webkit-transform: translate3d(0, 25px, 0);
+    transform: translate3d(0, 25px, 0);
+  }
+
+  75% {
+    -webkit-transform: translate3d(0, -10px, 0);
+    transform: translate3d(0, -10px, 0);
+  }
+
+  90% {
+    -webkit-transform: translate3d(0, 5px, 0);
+    transform: translate3d(0, 5px, 0);
+  }
+
+  to {
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+.bounceInDown {
+  -webkit-animation-name: bounceInDown;
+  animation-name: bounceInDown;
+}
+
+@-webkit-keyframes bounceInLeft {
+  from, 60%, 75%, 90%, to {
+    -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+  }
+
+  0% {
+    opacity: 0;
+    -webkit-transform: translate3d(-3000px, 0, 0);
+    transform: translate3d(-3000px, 0, 0);
+  }
+
+  60% {
+    opacity: 1;
+    -webkit-transform: translate3d(25px, 0, 0);
+    transform: translate3d(25px, 0, 0);
+  }
+
+  75% {
+    -webkit-transform: translate3d(-10px, 0, 0);
+    transform: translate3d(-10px, 0, 0);
+  }
+
+  90% {
+    -webkit-transform: translate3d(5px, 0, 0);
+    transform: translate3d(5px, 0, 0);
+  }
+
+  to {
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+@keyframes bounceInLeft {
+  from, 60%, 75%, 90%, to {
+    -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+  }
+
+  0% {
+    opacity: 0;
+    -webkit-transform: translate3d(-3000px, 0, 0);
+    transform: translate3d(-3000px, 0, 0);
+  }
+
+  60% {
+    opacity: 1;
+    -webkit-transform: translate3d(25px, 0, 0);
+    transform: translate3d(25px, 0, 0);
+  }
+
+  75% {
+    -webkit-transform: translate3d(-10px, 0, 0);
+    transform: translate3d(-10px, 0, 0);
+  }
+
+  90% {
+    -webkit-transform: translate3d(5px, 0, 0);
+    transform: translate3d(5px, 0, 0);
+  }
+
+  to {
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+.bounceInLeft {
+  -webkit-animation-name: bounceInLeft;
+  animation-name: bounceInLeft;
+}
+
+@-webkit-keyframes bounceInRight {
+  from, 60%, 75%, 90%, to {
+    -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+  }
+
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(3000px, 0, 0);
+    transform: translate3d(3000px, 0, 0);
+  }
+
+  60% {
+    opacity: 1;
+    -webkit-transform: translate3d(-25px, 0, 0);
+    transform: translate3d(-25px, 0, 0);
+  }
+
+  75% {
+    -webkit-transform: translate3d(10px, 0, 0);
+    transform: translate3d(10px, 0, 0);
+  }
+
+  90% {
+    -webkit-transform: translate3d(-5px, 0, 0);
+    transform: translate3d(-5px, 0, 0);
+  }
+
+  to {
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+@keyframes bounceInRight {
+  from, 60%, 75%, 90%, to {
+    -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+  }
+
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(3000px, 0, 0);
+    transform: translate3d(3000px, 0, 0);
+  }
+
+  60% {
+    opacity: 1;
+    -webkit-transform: translate3d(-25px, 0, 0);
+    transform: translate3d(-25px, 0, 0);
+  }
+
+  75% {
+    -webkit-transform: translate3d(10px, 0, 0);
+    transform: translate3d(10px, 0, 0);
+  }
+
+  90% {
+    -webkit-transform: translate3d(-5px, 0, 0);
+    transform: translate3d(-5px, 0, 0);
+  }
+
+  to {
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+.bounceInRight {
+  -webkit-animation-name: bounceInRight;
+  animation-name: bounceInRight;
+}
+
+@-webkit-keyframes bounceInUp {
+  from, 60%, 75%, 90%, to {
+    -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+  }
+
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(0, 3000px, 0);
+    transform: translate3d(0, 3000px, 0);
+  }
+
+  60% {
+    opacity: 1;
+    -webkit-transform: translate3d(0, -20px, 0);
+    transform: translate3d(0, -20px, 0);
+  }
+
+  75% {
+    -webkit-transform: translate3d(0, 10px, 0);
+    transform: translate3d(0, 10px, 0);
+  }
+
+  90% {
+    -webkit-transform: translate3d(0, -5px, 0);
+    transform: translate3d(0, -5px, 0);
+  }
+
+  to {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+@keyframes bounceInUp {
+  from, 60%, 75%, 90%, to {
+    -webkit-animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+    animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
+  }
+
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(0, 3000px, 0);
+    transform: translate3d(0, 3000px, 0);
+  }
+
+  60% {
+    opacity: 1;
+    -webkit-transform: translate3d(0, -20px, 0);
+    transform: translate3d(0, -20px, 0);
+  }
+
+  75% {
+    -webkit-transform: translate3d(0, 10px, 0);
+    transform: translate3d(0, 10px, 0);
+  }
+
+  90% {
+    -webkit-transform: translate3d(0, -5px, 0);
+    transform: translate3d(0, -5px, 0);
+  }
+
+  to {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+.bounceInUp {
+  -webkit-animation-name: bounceInUp;
+  animation-name: bounceInUp;
+}
+
+@-webkit-keyframes bounceOut {
+  20% {
+    -webkit-transform: scale3d(.9, .9, .9);
+    transform: scale3d(.9, .9, .9);
+  }
+
+  50%, 55% {
+    opacity: 1;
+    -webkit-transform: scale3d(1.1, 1.1, 1.1);
+    transform: scale3d(1.1, 1.1, 1.1);
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: scale3d(.3, .3, .3);
+    transform: scale3d(.3, .3, .3);
+  }
+}
+
+@keyframes bounceOut {
+  20% {
+    -webkit-transform: scale3d(.9, .9, .9);
+    transform: scale3d(.9, .9, .9);
+  }
+
+  50%, 55% {
+    opacity: 1;
+    -webkit-transform: scale3d(1.1, 1.1, 1.1);
+    transform: scale3d(1.1, 1.1, 1.1);
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: scale3d(.3, .3, .3);
+    transform: scale3d(.3, .3, .3);
+  }
+}
+
+.bounceOut {
+  -webkit-animation-name: bounceOut;
+  animation-name: bounceOut;
+}
+
+@-webkit-keyframes bounceOutDown {
+  20% {
+    -webkit-transform: translate3d(0, 10px, 0);
+    transform: translate3d(0, 10px, 0);
+  }
+
+  40%, 45% {
+    opacity: 1;
+    -webkit-transform: translate3d(0, -20px, 0);
+    transform: translate3d(0, -20px, 0);
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(0, 2000px, 0);
+    transform: translate3d(0, 2000px, 0);
+  }
+}
+
+@keyframes bounceOutDown {
+  20% {
+    -webkit-transform: translate3d(0, 10px, 0);
+    transform: translate3d(0, 10px, 0);
+  }
+
+  40%, 45% {
+    opacity: 1;
+    -webkit-transform: translate3d(0, -20px, 0);
+    transform: translate3d(0, -20px, 0);
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(0, 2000px, 0);
+    transform: translate3d(0, 2000px, 0);
+  }
+}
+
+.bounceOutDown {
+  -webkit-animation-name: bounceOutDown;
+  animation-name: bounceOutDown;
+}
+
+@-webkit-keyframes bounceOutLeft {
+  20% {
+    opacity: 1;
+    -webkit-transform: translate3d(20px, 0, 0);
+    transform: translate3d(20px, 0, 0);
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(-2000px, 0, 0);
+    transform: translate3d(-2000px, 0, 0);
+  }
+}
+
+@keyframes bounceOutLeft {
+  20% {
+    opacity: 1;
+    -webkit-transform: translate3d(20px, 0, 0);
+    transform: translate3d(20px, 0, 0);
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(-2000px, 0, 0);
+    transform: translate3d(-2000px, 0, 0);
+  }
+}
+
+.bounceOutLeft {
+  -webkit-animation-name: bounceOutLeft;
+  animation-name: bounceOutLeft;
+}
+
+@-webkit-keyframes bounceOutRight {
+  20% {
+    opacity: 1;
+    -webkit-transform: translate3d(-20px, 0, 0);
+    transform: translate3d(-20px, 0, 0);
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(2000px, 0, 0);
+    transform: translate3d(2000px, 0, 0);
+  }
+}
+
+@keyframes bounceOutRight {
+  20% {
+    opacity: 1;
+    -webkit-transform: translate3d(-20px, 0, 0);
+    transform: translate3d(-20px, 0, 0);
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(2000px, 0, 0);
+    transform: translate3d(2000px, 0, 0);
+  }
+}
+
+.bounceOutRight {
+  -webkit-animation-name: bounceOutRight;
+  animation-name: bounceOutRight;
+}
+
+@-webkit-keyframes bounceOutUp {
+  20% {
+    -webkit-transform: translate3d(0, -10px, 0);
+    transform: translate3d(0, -10px, 0);
+  }
+
+  40%, 45% {
+    opacity: 1;
+    -webkit-transform: translate3d(0, 20px, 0);
+    transform: translate3d(0, 20px, 0);
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(0, -2000px, 0);
+    transform: translate3d(0, -2000px, 0);
+  }
+}
+
+@keyframes bounceOutUp {
+  20% {
+    -webkit-transform: translate3d(0, -10px, 0);
+    transform: translate3d(0, -10px, 0);
+  }
+
+  40%, 45% {
+    opacity: 1;
+    -webkit-transform: translate3d(0, 20px, 0);
+    transform: translate3d(0, 20px, 0);
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(0, -2000px, 0);
+    transform: translate3d(0, -2000px, 0);
+  }
+}
+
+.bounceOutUp {
+  -webkit-animation-name: bounceOutUp;
+  animation-name: bounceOutUp;
+}
+
+@-webkit-keyframes fadeIn {
+  from {
+    opacity: 0;
+  }
+
+  to {
+    opacity: 1;
+  }
+}
+
+@keyframes fadeIn {
+  from {
+    opacity: 0;
+  }
+
+  to {
+    opacity: 1;
+  }
+}
+
+.fadeIn {
+  -webkit-animation-name: fadeIn;
+  animation-name: fadeIn;
+}
+
+@-webkit-keyframes fadeInDown {
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(0, -100%, 0);
+    transform: translate3d(0, -100%, 0);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+@keyframes fadeInDown {
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(0, -100%, 0);
+    transform: translate3d(0, -100%, 0);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+.fadeInDown {
+  -webkit-animation-name: fadeInDown;
+  animation-name: fadeInDown;
+}
+
+@-webkit-keyframes fadeInDownBig {
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(0, -2000px, 0);
+    transform: translate3d(0, -2000px, 0);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+@keyframes fadeInDownBig {
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(0, -2000px, 0);
+    transform: translate3d(0, -2000px, 0);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+.fadeInDownBig {
+  -webkit-animation-name: fadeInDownBig;
+  animation-name: fadeInDownBig;
+}
+
+@-webkit-keyframes fadeInLeft {
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(-100%, 0, 0);
+    transform: translate3d(-100%, 0, 0);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+@keyframes fadeInLeft {
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(-100%, 0, 0);
+    transform: translate3d(-100%, 0, 0);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+.fadeInLeft {
+  -webkit-animation-name: fadeInLeft;
+  animation-name: fadeInLeft;
+}
+
+@-webkit-keyframes fadeInLeftBig {
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(-2000px, 0, 0);
+    transform: translate3d(-2000px, 0, 0);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+@keyframes fadeInLeftBig {
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(-2000px, 0, 0);
+    transform: translate3d(-2000px, 0, 0);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+.fadeInLeftBig {
+  -webkit-animation-name: fadeInLeftBig;
+  animation-name: fadeInLeftBig;
+}
+
+@-webkit-keyframes fadeInRight {
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(100%, 0, 0);
+    transform: translate3d(100%, 0, 0);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+@keyframes fadeInRight {
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(100%, 0, 0);
+    transform: translate3d(100%, 0, 0);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+.fadeInRight {
+  -webkit-animation-name: fadeInRight;
+  animation-name: fadeInRight;
+}
+
+@-webkit-keyframes fadeInRightBig {
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(2000px, 0, 0);
+    transform: translate3d(2000px, 0, 0);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+@keyframes fadeInRightBig {
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(2000px, 0, 0);
+    transform: translate3d(2000px, 0, 0);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+.fadeInRightBig {
+  -webkit-animation-name: fadeInRightBig;
+  animation-name: fadeInRightBig;
+}
+
+@-webkit-keyframes fadeInUp {
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(0, 100%, 0);
+    transform: translate3d(0, 100%, 0);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+@keyframes fadeInUp {
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(0, 100%, 0);
+    transform: translate3d(0, 100%, 0);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+.fadeInUp {
+  -webkit-animation-name: fadeInUp;
+  animation-name: fadeInUp;
+}
+
+@-webkit-keyframes fadeInUpBig {
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(0, 2000px, 0);
+    transform: translate3d(0, 2000px, 0);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+@keyframes fadeInUpBig {
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(0, 2000px, 0);
+    transform: translate3d(0, 2000px, 0);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+.fadeInUpBig {
+  -webkit-animation-name: fadeInUpBig;
+  animation-name: fadeInUpBig;
+}
+
+@-webkit-keyframes fadeOut {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+  }
+}
+
+@keyframes fadeOut {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+  }
+}
+
+.fadeOut {
+  -webkit-animation-name: fadeOut;
+  animation-name: fadeOut;
+}
+
+@-webkit-keyframes fadeOutDown {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(0, 100%, 0);
+    transform: translate3d(0, 100%, 0);
+  }
+}
+
+@keyframes fadeOutDown {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(0, 100%, 0);
+    transform: translate3d(0, 100%, 0);
+  }
+}
+
+.fadeOutDown {
+  -webkit-animation-name: fadeOutDown;
+  animation-name: fadeOutDown;
+}
+
+@-webkit-keyframes fadeOutDownBig {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(0, 2000px, 0);
+    transform: translate3d(0, 2000px, 0);
+  }
+}
+
+@keyframes fadeOutDownBig {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(0, 2000px, 0);
+    transform: translate3d(0, 2000px, 0);
+  }
+}
+
+.fadeOutDownBig {
+  -webkit-animation-name: fadeOutDownBig;
+  animation-name: fadeOutDownBig;
+}
+
+@-webkit-keyframes fadeOutLeft {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(-100%, 0, 0);
+    transform: translate3d(-100%, 0, 0);
+  }
+}
+
+@keyframes fadeOutLeft {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(-100%, 0, 0);
+    transform: translate3d(-100%, 0, 0);
+  }
+}
+
+.fadeOutLeft {
+  -webkit-animation-name: fadeOutLeft;
+  animation-name: fadeOutLeft;
+}
+
+@-webkit-keyframes fadeOutLeftBig {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(-2000px, 0, 0);
+    transform: translate3d(-2000px, 0, 0);
+  }
+}
+
+@keyframes fadeOutLeftBig {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(-2000px, 0, 0);
+    transform: translate3d(-2000px, 0, 0);
+  }
+}
+
+.fadeOutLeftBig {
+  -webkit-animation-name: fadeOutLeftBig;
+  animation-name: fadeOutLeftBig;
+}
+
+@-webkit-keyframes fadeOutRight {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(100%, 0, 0);
+    transform: translate3d(100%, 0, 0);
+  }
+}
+
+@keyframes fadeOutRight {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(100%, 0, 0);
+    transform: translate3d(100%, 0, 0);
+  }
+}
+
+.fadeOutRight {
+  -webkit-animation-name: fadeOutRight;
+  animation-name: fadeOutRight;
+}
+
+@-webkit-keyframes fadeOutRightBig {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(2000px, 0, 0);
+    transform: translate3d(2000px, 0, 0);
+  }
+}
+
+@keyframes fadeOutRightBig {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(2000px, 0, 0);
+    transform: translate3d(2000px, 0, 0);
+  }
+}
+
+.fadeOutRightBig {
+  -webkit-animation-name: fadeOutRightBig;
+  animation-name: fadeOutRightBig;
+}
+
+@-webkit-keyframes fadeOutUp {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(0, -100%, 0);
+    transform: translate3d(0, -100%, 0);
+  }
+}
+
+@keyframes fadeOutUp {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(0, -100%, 0);
+    transform: translate3d(0, -100%, 0);
+  }
+}
+
+.fadeOutUp {
+  -webkit-animation-name: fadeOutUp;
+  animation-name: fadeOutUp;
+}
+
+@-webkit-keyframes fadeOutUpBig {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(0, -2000px, 0);
+    transform: translate3d(0, -2000px, 0);
+  }
+}
+
+@keyframes fadeOutUpBig {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(0, -2000px, 0);
+    transform: translate3d(0, -2000px, 0);
+  }
+}
+
+.fadeOutUpBig {
+  -webkit-animation-name: fadeOutUpBig;
+  animation-name: fadeOutUpBig;
+}
+
+@-webkit-keyframes flip {
+  from {
+    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
+    transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
+    -webkit-animation-timing-function: ease-out;
+    animation-timing-function: ease-out;
+  }
+
+  40% {
+    -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
+    transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
+    -webkit-animation-timing-function: ease-out;
+    animation-timing-function: ease-out;
+  }
+
+  50% {
+    -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
+    transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
+    -webkit-animation-timing-function: ease-in;
+    animation-timing-function: ease-in;
+  }
+
+  80% {
+    -webkit-transform: perspective(400px) scale3d(.95, .95, .95);
+    transform: perspective(400px) scale3d(.95, .95, .95);
+    -webkit-animation-timing-function: ease-in;
+    animation-timing-function: ease-in;
+  }
+
+  to {
+    -webkit-transform: perspective(400px);
+    transform: perspective(400px);
+    -webkit-animation-timing-function: ease-in;
+    animation-timing-function: ease-in;
+  }
+}
+
+@keyframes flip {
+  from {
+    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
+    transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
+    -webkit-animation-timing-function: ease-out;
+    animation-timing-function: ease-out;
+  }
+
+  40% {
+    -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
+    transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
+    -webkit-animation-timing-function: ease-out;
+    animation-timing-function: ease-out;
+  }
+
+  50% {
+    -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
+    transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
+    -webkit-animation-timing-function: ease-in;
+    animation-timing-function: ease-in;
+  }
+
+  80% {
+    -webkit-transform: perspective(400px) scale3d(.95, .95, .95);
+    transform: perspective(400px) scale3d(.95, .95, .95);
+    -webkit-animation-timing-function: ease-in;
+    animation-timing-function: ease-in;
+  }
+
+  to {
+    -webkit-transform: perspective(400px);
+    transform: perspective(400px);
+    -webkit-animation-timing-function: ease-in;
+    animation-timing-function: ease-in;
+  }
+}
+
+.animated.flip {
+  -webkit-backface-visibility: visible;
+  backface-visibility: visible;
+  -webkit-animation-name: flip;
+  animation-name: flip;
+}
+
+@-webkit-keyframes flipInX {
+  from {
+    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+    -webkit-animation-timing-function: ease-in;
+    animation-timing-function: ease-in;
+    opacity: 0;
+  }
+
+  40% {
+    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+    -webkit-animation-timing-function: ease-in;
+    animation-timing-function: ease-in;
+  }
+
+  60% {
+    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
+    transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
+    opacity: 1;
+  }
+
+  80% {
+    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
+    transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
+  }
+
+  to {
+    -webkit-transform: perspective(400px);
+    transform: perspective(400px);
+  }
+}
+
+@keyframes flipInX {
+  from {
+    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+    -webkit-animation-timing-function: ease-in;
+    animation-timing-function: ease-in;
+    opacity: 0;
+  }
+
+  40% {
+    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+    -webkit-animation-timing-function: ease-in;
+    animation-timing-function: ease-in;
+  }
+
+  60% {
+    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
+    transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
+    opacity: 1;
+  }
+
+  80% {
+    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
+    transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
+  }
+
+  to {
+    -webkit-transform: perspective(400px);
+    transform: perspective(400px);
+  }
+}
+
+.flipInX {
+  -webkit-backface-visibility: visible !important;
+  backface-visibility: visible !important;
+  -webkit-animation-name: flipInX;
+  animation-name: flipInX;
+}
+
+@-webkit-keyframes flipInY {
+  from {
+    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+    transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+    -webkit-animation-timing-function: ease-in;
+    animation-timing-function: ease-in;
+    opacity: 0;
+  }
+
+  40% {
+    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
+    transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
+    -webkit-animation-timing-function: ease-in;
+    animation-timing-function: ease-in;
+  }
+
+  60% {
+    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
+    transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
+    opacity: 1;
+  }
+
+  80% {
+    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
+    transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
+  }
+
+  to {
+    -webkit-transform: perspective(400px);
+    transform: perspective(400px);
+  }
+}
+
+@keyframes flipInY {
+  from {
+    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+    transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+    -webkit-animation-timing-function: ease-in;
+    animation-timing-function: ease-in;
+    opacity: 0;
+  }
+
+  40% {
+    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
+    transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
+    -webkit-animation-timing-function: ease-in;
+    animation-timing-function: ease-in;
+  }
+
+  60% {
+    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
+    transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
+    opacity: 1;
+  }
+
+  80% {
+    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
+    transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
+  }
+
+  to {
+    -webkit-transform: perspective(400px);
+    transform: perspective(400px);
+  }
+}
+
+.flipInY {
+  -webkit-backface-visibility: visible !important;
+  backface-visibility: visible !important;
+  -webkit-animation-name: flipInY;
+  animation-name: flipInY;
+}
+
+@-webkit-keyframes flipOutX {
+  from {
+    -webkit-transform: perspective(400px);
+    transform: perspective(400px);
+  }
+
+  30% {
+    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+    opacity: 0;
+  }
+}
+
+@keyframes flipOutX {
+  from {
+    -webkit-transform: perspective(400px);
+    transform: perspective(400px);
+  }
+
+  30% {
+    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+    transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
+    opacity: 0;
+  }
+}
+
+.flipOutX {
+  -webkit-animation-name: flipOutX;
+  animation-name: flipOutX;
+  -webkit-backface-visibility: visible !important;
+  backface-visibility: visible !important;
+}
+
+@-webkit-keyframes flipOutY {
+  from {
+    -webkit-transform: perspective(400px);
+    transform: perspective(400px);
+  }
+
+  30% {
+    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
+    transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+    transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+    opacity: 0;
+  }
+}
+
+@keyframes flipOutY {
+  from {
+    -webkit-transform: perspective(400px);
+    transform: perspective(400px);
+  }
+
+  30% {
+    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
+    transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+    transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
+    opacity: 0;
+  }
+}
+
+.flipOutY {
+  -webkit-backface-visibility: visible !important;
+  backface-visibility: visible !important;
+  -webkit-animation-name: flipOutY;
+  animation-name: flipOutY;
+}
+
+@-webkit-keyframes lightSpeedIn {
+  from {
+    -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg);
+    transform: translate3d(100%, 0, 0) skewX(-30deg);
+    opacity: 0;
+  }
+
+  60% {
+    -webkit-transform: skewX(20deg);
+    transform: skewX(20deg);
+    opacity: 1;
+  }
+
+  80% {
+    -webkit-transform: skewX(-5deg);
+    transform: skewX(-5deg);
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform: none;
+    transform: none;
+    opacity: 1;
+  }
+}
+
+@keyframes lightSpeedIn {
+  from {
+    -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg);
+    transform: translate3d(100%, 0, 0) skewX(-30deg);
+    opacity: 0;
+  }
+
+  60% {
+    -webkit-transform: skewX(20deg);
+    transform: skewX(20deg);
+    opacity: 1;
+  }
+
+  80% {
+    -webkit-transform: skewX(-5deg);
+    transform: skewX(-5deg);
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform: none;
+    transform: none;
+    opacity: 1;
+  }
+}
+
+.lightSpeedIn {
+  -webkit-animation-name: lightSpeedIn;
+  animation-name: lightSpeedIn;
+  -webkit-animation-timing-function: ease-out;
+  animation-timing-function: ease-out;
+}
+
+@-webkit-keyframes lightSpeedOut {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform: translate3d(100%, 0, 0) skewX(30deg);
+    transform: translate3d(100%, 0, 0) skewX(30deg);
+    opacity: 0;
+  }
+}
+
+@keyframes lightSpeedOut {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform: translate3d(100%, 0, 0) skewX(30deg);
+    transform: translate3d(100%, 0, 0) skewX(30deg);
+    opacity: 0;
+  }
+}
+
+.lightSpeedOut {
+  -webkit-animation-name: lightSpeedOut;
+  animation-name: lightSpeedOut;
+  -webkit-animation-timing-function: ease-in;
+  animation-timing-function: ease-in;
+}
+
+@-webkit-keyframes rotateIn {
+  from {
+    -webkit-transform-origin: center;
+    transform-origin: center;
+    -webkit-transform: rotate3d(0, 0, 1, -200deg);
+    transform: rotate3d(0, 0, 1, -200deg);
+    opacity: 0;
+  }
+
+  to {
+    -webkit-transform-origin: center;
+    transform-origin: center;
+    -webkit-transform: none;
+    transform: none;
+    opacity: 1;
+  }
+}
+
+@keyframes rotateIn {
+  from {
+    -webkit-transform-origin: center;
+    transform-origin: center;
+    -webkit-transform: rotate3d(0, 0, 1, -200deg);
+    transform: rotate3d(0, 0, 1, -200deg);
+    opacity: 0;
+  }
+
+  to {
+    -webkit-transform-origin: center;
+    transform-origin: center;
+    -webkit-transform: none;
+    transform: none;
+    opacity: 1;
+  }
+}
+
+.rotateIn {
+  -webkit-animation-name: rotateIn;
+  animation-name: rotateIn;
+}
+
+@-webkit-keyframes rotateInDownLeft {
+  from {
+    -webkit-transform-origin: left bottom;
+    transform-origin: left bottom;
+    -webkit-transform: rotate3d(0, 0, 1, -45deg);
+    transform: rotate3d(0, 0, 1, -45deg);
+    opacity: 0;
+  }
+
+  to {
+    -webkit-transform-origin: left bottom;
+    transform-origin: left bottom;
+    -webkit-transform: none;
+    transform: none;
+    opacity: 1;
+  }
+}
+
+@keyframes rotateInDownLeft {
+  from {
+    -webkit-transform-origin: left bottom;
+    transform-origin: left bottom;
+    -webkit-transform: rotate3d(0, 0, 1, -45deg);
+    transform: rotate3d(0, 0, 1, -45deg);
+    opacity: 0;
+  }
+
+  to {
+    -webkit-transform-origin: left bottom;
+    transform-origin: left bottom;
+    -webkit-transform: none;
+    transform: none;
+    opacity: 1;
+  }
+}
+
+.rotateInDownLeft {
+  -webkit-animation-name: rotateInDownLeft;
+  animation-name: rotateInDownLeft;
+}
+
+@-webkit-keyframes rotateInDownRight {
+  from {
+    -webkit-transform-origin: right bottom;
+    transform-origin: right bottom;
+    -webkit-transform: rotate3d(0, 0, 1, 45deg);
+    transform: rotate3d(0, 0, 1, 45deg);
+    opacity: 0;
+  }
+
+  to {
+    -webkit-transform-origin: right bottom;
+    transform-origin: right bottom;
+    -webkit-transform: none;
+    transform: none;
+    opacity: 1;
+  }
+}
+
+@keyframes rotateInDownRight {
+  from {
+    -webkit-transform-origin: right bottom;
+    transform-origin: right bottom;
+    -webkit-transform: rotate3d(0, 0, 1, 45deg);
+    transform: rotate3d(0, 0, 1, 45deg);
+    opacity: 0;
+  }
+
+  to {
+    -webkit-transform-origin: right bottom;
+    transform-origin: right bottom;
+    -webkit-transform: none;
+    transform: none;
+    opacity: 1;
+  }
+}
+
+.rotateInDownRight {
+  -webkit-animation-name: rotateInDownRight;
+  animation-name: rotateInDownRight;
+}
+
+@-webkit-keyframes rotateInUpLeft {
+  from {
+    -webkit-transform-origin: left bottom;
+    transform-origin: left bottom;
+    -webkit-transform: rotate3d(0, 0, 1, 45deg);
+    transform: rotate3d(0, 0, 1, 45deg);
+    opacity: 0;
+  }
+
+  to {
+    -webkit-transform-origin: left bottom;
+    transform-origin: left bottom;
+    -webkit-transform: none;
+    transform: none;
+    opacity: 1;
+  }
+}
+
+@keyframes rotateInUpLeft {
+  from {
+    -webkit-transform-origin: left bottom;
+    transform-origin: left bottom;
+    -webkit-transform: rotate3d(0, 0, 1, 45deg);
+    transform: rotate3d(0, 0, 1, 45deg);
+    opacity: 0;
+  }
+
+  to {
+    -webkit-transform-origin: left bottom;
+    transform-origin: left bottom;
+    -webkit-transform: none;
+    transform: none;
+    opacity: 1;
+  }
+}
+
+.rotateInUpLeft {
+  -webkit-animation-name: rotateInUpLeft;
+  animation-name: rotateInUpLeft;
+}
+
+@-webkit-keyframes rotateInUpRight {
+  from {
+    -webkit-transform-origin: right bottom;
+    transform-origin: right bottom;
+    -webkit-transform: rotate3d(0, 0, 1, -90deg);
+    transform: rotate3d(0, 0, 1, -90deg);
+    opacity: 0;
+  }
+
+  to {
+    -webkit-transform-origin: right bottom;
+    transform-origin: right bottom;
+    -webkit-transform: none;
+    transform: none;
+    opacity: 1;
+  }
+}
+
+@keyframes rotateInUpRight {
+  from {
+    -webkit-transform-origin: right bottom;
+    transform-origin: right bottom;
+    -webkit-transform: rotate3d(0, 0, 1, -90deg);
+    transform: rotate3d(0, 0, 1, -90deg);
+    opacity: 0;
+  }
+
+  to {
+    -webkit-transform-origin: right bottom;
+    transform-origin: right bottom;
+    -webkit-transform: none;
+    transform: none;
+    opacity: 1;
+  }
+}
+
+.rotateInUpRight {
+  -webkit-animation-name: rotateInUpRight;
+  animation-name: rotateInUpRight;
+}
+
+@-webkit-keyframes rotateOut {
+  from {
+    -webkit-transform-origin: center;
+    transform-origin: center;
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform-origin: center;
+    transform-origin: center;
+    -webkit-transform: rotate3d(0, 0, 1, 200deg);
+    transform: rotate3d(0, 0, 1, 200deg);
+    opacity: 0;
+  }
+}
+
+@keyframes rotateOut {
+  from {
+    -webkit-transform-origin: center;
+    transform-origin: center;
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform-origin: center;
+    transform-origin: center;
+    -webkit-transform: rotate3d(0, 0, 1, 200deg);
+    transform: rotate3d(0, 0, 1, 200deg);
+    opacity: 0;
+  }
+}
+
+.rotateOut {
+  -webkit-animation-name: rotateOut;
+  animation-name: rotateOut;
+}
+
+@-webkit-keyframes rotateOutDownLeft {
+  from {
+    -webkit-transform-origin: left bottom;
+    transform-origin: left bottom;
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform-origin: left bottom;
+    transform-origin: left bottom;
+    -webkit-transform: rotate3d(0, 0, 1, 45deg);
+    transform: rotate3d(0, 0, 1, 45deg);
+    opacity: 0;
+  }
+}
+
+@keyframes rotateOutDownLeft {
+  from {
+    -webkit-transform-origin: left bottom;
+    transform-origin: left bottom;
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform-origin: left bottom;
+    transform-origin: left bottom;
+    -webkit-transform: rotate3d(0, 0, 1, 45deg);
+    transform: rotate3d(0, 0, 1, 45deg);
+    opacity: 0;
+  }
+}
+
+.rotateOutDownLeft {
+  -webkit-animation-name: rotateOutDownLeft;
+  animation-name: rotateOutDownLeft;
+}
+
+@-webkit-keyframes rotateOutDownRight {
+  from {
+    -webkit-transform-origin: right bottom;
+    transform-origin: right bottom;
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform-origin: right bottom;
+    transform-origin: right bottom;
+    -webkit-transform: rotate3d(0, 0, 1, -45deg);
+    transform: rotate3d(0, 0, 1, -45deg);
+    opacity: 0;
+  }
+}
+
+@keyframes rotateOutDownRight {
+  from {
+    -webkit-transform-origin: right bottom;
+    transform-origin: right bottom;
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform-origin: right bottom;
+    transform-origin: right bottom;
+    -webkit-transform: rotate3d(0, 0, 1, -45deg);
+    transform: rotate3d(0, 0, 1, -45deg);
+    opacity: 0;
+  }
+}
+
+.rotateOutDownRight {
+  -webkit-animation-name: rotateOutDownRight;
+  animation-name: rotateOutDownRight;
+}
+
+@-webkit-keyframes rotateOutUpLeft {
+  from {
+    -webkit-transform-origin: left bottom;
+    transform-origin: left bottom;
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform-origin: left bottom;
+    transform-origin: left bottom;
+    -webkit-transform: rotate3d(0, 0, 1, -45deg);
+    transform: rotate3d(0, 0, 1, -45deg);
+    opacity: 0;
+  }
+}
+
+@keyframes rotateOutUpLeft {
+  from {
+    -webkit-transform-origin: left bottom;
+    transform-origin: left bottom;
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform-origin: left bottom;
+    transform-origin: left bottom;
+    -webkit-transform: rotate3d(0, 0, 1, -45deg);
+    transform: rotate3d(0, 0, 1, -45deg);
+    opacity: 0;
+  }
+}
+
+.rotateOutUpLeft {
+  -webkit-animation-name: rotateOutUpLeft;
+  animation-name: rotateOutUpLeft;
+}
+
+@-webkit-keyframes rotateOutUpRight {
+  from {
+    -webkit-transform-origin: right bottom;
+    transform-origin: right bottom;
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform-origin: right bottom;
+    transform-origin: right bottom;
+    -webkit-transform: rotate3d(0, 0, 1, 90deg);
+    transform: rotate3d(0, 0, 1, 90deg);
+    opacity: 0;
+  }
+}
+
+@keyframes rotateOutUpRight {
+  from {
+    -webkit-transform-origin: right bottom;
+    transform-origin: right bottom;
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform-origin: right bottom;
+    transform-origin: right bottom;
+    -webkit-transform: rotate3d(0, 0, 1, 90deg);
+    transform: rotate3d(0, 0, 1, 90deg);
+    opacity: 0;
+  }
+}
+
+.rotateOutUpRight {
+  -webkit-animation-name: rotateOutUpRight;
+  animation-name: rotateOutUpRight;
+}
+
+@-webkit-keyframes hinge {
+  0% {
+    -webkit-transform-origin: top left;
+    transform-origin: top left;
+    -webkit-animation-timing-function: ease-in-out;
+    animation-timing-function: ease-in-out;
+  }
+
+  20%, 60% {
+    -webkit-transform: rotate3d(0, 0, 1, 80deg);
+    transform: rotate3d(0, 0, 1, 80deg);
+    -webkit-transform-origin: top left;
+    transform-origin: top left;
+    -webkit-animation-timing-function: ease-in-out;
+    animation-timing-function: ease-in-out;
+  }
+
+  40%, 80% {
+    -webkit-transform: rotate3d(0, 0, 1, 60deg);
+    transform: rotate3d(0, 0, 1, 60deg);
+    -webkit-transform-origin: top left;
+    transform-origin: top left;
+    -webkit-animation-timing-function: ease-in-out;
+    animation-timing-function: ease-in-out;
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform: translate3d(0, 700px, 0);
+    transform: translate3d(0, 700px, 0);
+    opacity: 0;
+  }
+}
+
+@keyframes hinge {
+  0% {
+    -webkit-transform-origin: top left;
+    transform-origin: top left;
+    -webkit-animation-timing-function: ease-in-out;
+    animation-timing-function: ease-in-out;
+  }
+
+  20%, 60% {
+    -webkit-transform: rotate3d(0, 0, 1, 80deg);
+    transform: rotate3d(0, 0, 1, 80deg);
+    -webkit-transform-origin: top left;
+    transform-origin: top left;
+    -webkit-animation-timing-function: ease-in-out;
+    animation-timing-function: ease-in-out;
+  }
+
+  40%, 80% {
+    -webkit-transform: rotate3d(0, 0, 1, 60deg);
+    transform: rotate3d(0, 0, 1, 60deg);
+    -webkit-transform-origin: top left;
+    transform-origin: top left;
+    -webkit-animation-timing-function: ease-in-out;
+    animation-timing-function: ease-in-out;
+    opacity: 1;
+  }
+
+  to {
+    -webkit-transform: translate3d(0, 700px, 0);
+    transform: translate3d(0, 700px, 0);
+    opacity: 0;
+  }
+}
+
+.hinge {
+  -webkit-animation-name: hinge;
+  animation-name: hinge;
+}
+
+/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
+
+@-webkit-keyframes rollIn {
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
+    transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+@keyframes rollIn {
+  from {
+    opacity: 0;
+    -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
+    transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
+  }
+
+  to {
+    opacity: 1;
+    -webkit-transform: none;
+    transform: none;
+  }
+}
+
+.rollIn {
+  -webkit-animation-name: rollIn;
+  animation-name: rollIn;
+}
+
+/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
+
+@-webkit-keyframes rollOut {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
+    transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
+  }
+}
+
+@keyframes rollOut {
+  from {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
+    transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
+  }
+}
+
+.rollOut {
+  -webkit-animation-name: rollOut;
+  animation-name: rollOut;
+}
+
+@-webkit-keyframes zoomIn {
+  from {
+    opacity: 0;
+    -webkit-transform: scale3d(.3, .3, .3);
+    transform: scale3d(.3, .3, .3);
+  }
+
+  50% {
+    opacity: 1;
+  }
+}
+
+@keyframes zoomIn {
+  from {
+    opacity: 0;
+    -webkit-transform: scale3d(.3, .3, .3);
+    transform: scale3d(.3, .3, .3);
+  }
+
+  50% {
+    opacity: 1;
+  }
+}
+
+.zoomIn {
+  -webkit-animation-name: zoomIn;
+  animation-name: zoomIn;
+}
+
+@-webkit-keyframes zoomInDown {
+  from {
+    opacity: 0;
+    -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);
+    transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+  }
+
+  60% {
+    opacity: 1;
+    -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+    transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+  }
+}
+
+@keyframes zoomInDown {
+  from {
+    opacity: 0;
+    -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);
+    transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+  }
+
+  60% {
+    opacity: 1;
+    -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+    transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+  }
+}
+
+.zoomInDown {
+  -webkit-animation-name: zoomInDown;
+  animation-name: zoomInDown;
+}
+
+@-webkit-keyframes zoomInLeft {
+  from {
+    opacity: 0;
+    -webkit-transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);
+    transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+  }
+
+  60% {
+    opacity: 1;
+    -webkit-transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);
+    transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+  }
+}
+
+@keyframes zoomInLeft {
+  from {
+    opacity: 0;
+    -webkit-transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);
+    transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+  }
+
+  60% {
+    opacity: 1;
+    -webkit-transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);
+    transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+  }
+}
+
+.zoomInLeft {
+  -webkit-animation-name: zoomInLeft;
+  animation-name: zoomInLeft;
+}
+
+@-webkit-keyframes zoomInRight {
+  from {
+    opacity: 0;
+    -webkit-transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);
+    transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+  }
+
+  60% {
+    opacity: 1;
+    -webkit-transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);
+    transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+  }
+}
+
+@keyframes zoomInRight {
+  from {
+    opacity: 0;
+    -webkit-transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);
+    transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+  }
+
+  60% {
+    opacity: 1;
+    -webkit-transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);
+    transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+  }
+}
+
+.zoomInRight {
+  -webkit-animation-name: zoomInRight;
+  animation-name: zoomInRight;
+}
+
+@-webkit-keyframes zoomInUp {
+  from {
+    opacity: 0;
+    -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);
+    transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+  }
+
+  60% {
+    opacity: 1;
+    -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+    transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+  }
+}
+
+@keyframes zoomInUp {
+  from {
+    opacity: 0;
+    -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);
+    transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+  }
+
+  60% {
+    opacity: 1;
+    -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+    transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+  }
+}
+
+.zoomInUp {
+  -webkit-animation-name: zoomInUp;
+  animation-name: zoomInUp;
+}
+
+@-webkit-keyframes zoomOut {
+  from {
+    opacity: 1;
+  }
+
+  50% {
+    opacity: 0;
+    -webkit-transform: scale3d(.3, .3, .3);
+    transform: scale3d(.3, .3, .3);
+  }
+
+  to {
+    opacity: 0;
+  }
+}
+
+@keyframes zoomOut {
+  from {
+    opacity: 1;
+  }
+
+  50% {
+    opacity: 0;
+    -webkit-transform: scale3d(.3, .3, .3);
+    transform: scale3d(.3, .3, .3);
+  }
+
+  to {
+    opacity: 0;
+  }
+}
+
+.zoomOut {
+  -webkit-animation-name: zoomOut;
+  animation-name: zoomOut;
+}
+
+@-webkit-keyframes zoomOutDown {
+  40% {
+    opacity: 1;
+    -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+    transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);
+    transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);
+    -webkit-transform-origin: center bottom;
+    transform-origin: center bottom;
+    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+  }
+}
+
+@keyframes zoomOutDown {
+  40% {
+    opacity: 1;
+    -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+    transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);
+    transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);
+    -webkit-transform-origin: center bottom;
+    transform-origin: center bottom;
+    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+  }
+}
+
+.zoomOutDown {
+  -webkit-animation-name: zoomOutDown;
+  animation-name: zoomOutDown;
+}
+
+@-webkit-keyframes zoomOutLeft {
+  40% {
+    opacity: 1;
+    -webkit-transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0);
+    transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0);
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: scale(.1) translate3d(-2000px, 0, 0);
+    transform: scale(.1) translate3d(-2000px, 0, 0);
+    -webkit-transform-origin: left center;
+    transform-origin: left center;
+  }
+}
+
+@keyframes zoomOutLeft {
+  40% {
+    opacity: 1;
+    -webkit-transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0);
+    transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0);
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: scale(.1) translate3d(-2000px, 0, 0);
+    transform: scale(.1) translate3d(-2000px, 0, 0);
+    -webkit-transform-origin: left center;
+    transform-origin: left center;
+  }
+}
+
+.zoomOutLeft {
+  -webkit-animation-name: zoomOutLeft;
+  animation-name: zoomOutLeft;
+}
+
+@-webkit-keyframes zoomOutRight {
+  40% {
+    opacity: 1;
+    -webkit-transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0);
+    transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0);
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: scale(.1) translate3d(2000px, 0, 0);
+    transform: scale(.1) translate3d(2000px, 0, 0);
+    -webkit-transform-origin: right center;
+    transform-origin: right center;
+  }
+}
+
+@keyframes zoomOutRight {
+  40% {
+    opacity: 1;
+    -webkit-transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0);
+    transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0);
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: scale(.1) translate3d(2000px, 0, 0);
+    transform: scale(.1) translate3d(2000px, 0, 0);
+    -webkit-transform-origin: right center;
+    transform-origin: right center;
+  }
+}
+
+.zoomOutRight {
+  -webkit-animation-name: zoomOutRight;
+  animation-name: zoomOutRight;
+}
+
+@-webkit-keyframes zoomOutUp {
+  40% {
+    opacity: 1;
+    -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+    transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);
+    transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);
+    -webkit-transform-origin: center bottom;
+    transform-origin: center bottom;
+    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+  }
+}
+
+@keyframes zoomOutUp {
+  40% {
+    opacity: 1;
+    -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+    transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
+    -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+    animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
+  }
+
+  to {
+    opacity: 0;
+    -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);
+    transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);
+    -webkit-transform-origin: center bottom;
+    transform-origin: center bottom;
+    -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+    animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
+  }
+}
+
+.zoomOutUp {
+  -webkit-animation-name: zoomOutUp;
+  animation-name: zoomOutUp;
+}
+
+@-webkit-keyframes slideInDown {
+  from {
+    -webkit-transform: translate3d(0, -100%, 0);
+    transform: translate3d(0, -100%, 0);
+    visibility: visible;
+  }
+
+  to {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+@keyframes slideInDown {
+  from {
+    -webkit-transform: translate3d(0, -100%, 0);
+    transform: translate3d(0, -100%, 0);
+    visibility: visible;
+  }
+
+  to {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+.slideInDown {
+  -webkit-animation-name: slideInDown;
+  animation-name: slideInDown;
+}
+
+@-webkit-keyframes slideInLeft {
+  from {
+    -webkit-transform: translate3d(-100%, 0, 0);
+    transform: translate3d(-100%, 0, 0);
+    visibility: visible;
+  }
+
+  to {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+@keyframes slideInLeft {
+  from {
+    -webkit-transform: translate3d(-100%, 0, 0);
+    transform: translate3d(-100%, 0, 0);
+    visibility: visible;
+  }
+
+  to {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+.slideInLeft {
+  -webkit-animation-name: slideInLeft;
+  animation-name: slideInLeft;
+}
+
+@-webkit-keyframes slideInRight {
+  from {
+    -webkit-transform: translate3d(100%, 0, 0);
+    transform: translate3d(100%, 0, 0);
+    visibility: visible;
+  }
+
+  to {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+@keyframes slideInRight {
+  from {
+    -webkit-transform: translate3d(100%, 0, 0);
+    transform: translate3d(100%, 0, 0);
+    visibility: visible;
+  }
+
+  to {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+.slideInRight {
+  -webkit-animation-name: slideInRight;
+  animation-name: slideInRight;
+}
+
+@-webkit-keyframes slideInUp {
+  from {
+    -webkit-transform: translate3d(0, 100%, 0);
+    transform: translate3d(0, 100%, 0);
+    visibility: visible;
+  }
+
+  to {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+@keyframes slideInUp {
+  from {
+    -webkit-transform: translate3d(0, 100%, 0);
+    transform: translate3d(0, 100%, 0);
+    visibility: visible;
+  }
+
+  to {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+}
+
+.slideInUp {
+  -webkit-animation-name: slideInUp;
+  animation-name: slideInUp;
+}
+
+@-webkit-keyframes slideOutDown {
+  from {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+
+  to {
+    visibility: hidden;
+    -webkit-transform: translate3d(0, 100%, 0);
+    transform: translate3d(0, 100%, 0);
+  }
+}
+
+@keyframes slideOutDown {
+  from {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+
+  to {
+    visibility: hidden;
+    -webkit-transform: translate3d(0, 100%, 0);
+    transform: translate3d(0, 100%, 0);
+  }
+}
+
+.slideOutDown {
+  -webkit-animation-name: slideOutDown;
+  animation-name: slideOutDown;
+}
+
+@-webkit-keyframes slideOutLeft {
+  from {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+
+  to {
+    visibility: hidden;
+    -webkit-transform: translate3d(-100%, 0, 0);
+    transform: translate3d(-100%, 0, 0);
+  }
+}
+
+@keyframes slideOutLeft {
+  from {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+
+  to {
+    visibility: hidden;
+    -webkit-transform: translate3d(-100%, 0, 0);
+    transform: translate3d(-100%, 0, 0);
+  }
+}
+
+.slideOutLeft {
+  -webkit-animation-name: slideOutLeft;
+  animation-name: slideOutLeft;
+}
+
+@-webkit-keyframes slideOutRight {
+  from {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+
+  to {
+    visibility: hidden;
+    -webkit-transform: translate3d(100%, 0, 0);
+    transform: translate3d(100%, 0, 0);
+  }
+}
+
+@keyframes slideOutRight {
+  from {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+
+  to {
+    visibility: hidden;
+    -webkit-transform: translate3d(100%, 0, 0);
+    transform: translate3d(100%, 0, 0);
+  }
+}
+
+.slideOutRight {
+  -webkit-animation-name: slideOutRight;
+  animation-name: slideOutRight;
+}
+
+@-webkit-keyframes slideOutUp {
+  from {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+
+  to {
+    visibility: hidden;
+    -webkit-transform: translate3d(0, -100%, 0);
+    transform: translate3d(0, -100%, 0);
+  }
+}
+
+@keyframes slideOutUp {
+  from {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+
+  to {
+    visibility: hidden;
+    -webkit-transform: translate3d(0, -100%, 0);
+    transform: translate3d(0, -100%, 0);
+  }
+}
+
+.slideOutUp {
+  -webkit-animation-name: slideOutUp;
+  animation-name: slideOutUp;
+}
diff --git a/docs/site/home/css/custome.css b/docs/site/home/css/custome.css
index 39d9991..15735a4 100644
--- a/docs/site/home/css/custome.css
+++ b/docs/site/home/css/custome.css
@@ -44,6 +44,9 @@
 .text-blue{
     color: #147AA4;
 }
+.text-orange{
+    color: #f08d49;
+}
 .hover-op-low li{
     transition: all 0.2s ease-in-out;
 }
diff --git a/docs/site/home/css/font-awesome.css b/docs/site/home/css/font-awesome.css
new file mode 100644
index 0000000..ee906a8
--- /dev/null
+++ b/docs/site/home/css/font-awesome.css
@@ -0,0 +1,2337 @@
+/*!
+ *  Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
+ *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ */
+/* FONT PATH
+ * -------------------------- */
+@font-face {
+  font-family: 'FontAwesome';
+  src: url('../fonts/fontawesome-webfont.eot?v=4.7.0');
+  src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');
+  font-weight: normal;
+  font-style: normal;
+}
+.fa {
+  display: inline-block;
+  font: normal normal normal 14px/1 FontAwesome;
+  font-size: inherit;
+  text-rendering: auto;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+/* makes the font 33% larger relative to the icon container */
+.fa-lg {
+  font-size: 1.33333333em;
+  line-height: 0.75em;
+  vertical-align: -15%;
+}
+.fa-2x {
+  font-size: 2em;
+}
+.fa-3x {
+  font-size: 3em;
+}
+.fa-4x {
+  font-size: 4em;
+}
+.fa-5x {
+  font-size: 5em;
+}
+.fa-fw {
+  width: 1.28571429em;
+  text-align: center;
+}
+.fa-ul {
+  padding-left: 0;
+  margin-left: 2.14285714em;
+  list-style-type: none;
+}
+.fa-ul > li {
+  position: relative;
+}
+.fa-li {
+  position: absolute;
+  left: -2.14285714em;
+  width: 2.14285714em;
+  top: 0.14285714em;
+  text-align: center;
+}
+.fa-li.fa-lg {
+  left: -1.85714286em;
+}
+.fa-border {
+  padding: .2em .25em .15em;
+  border: solid 0.08em #eeeeee;
+  border-radius: .1em;
+}
+.fa-pull-left {
+  float: left;
+}
+.fa-pull-right {
+  float: right;
+}
+.fa.fa-pull-left {
+  margin-right: .3em;
+}
+.fa.fa-pull-right {
+  margin-left: .3em;
+}
+/* Deprecated as of 4.4.0 */
+.pull-right {
+  float: right;
+}
+.pull-left {
+  float: left;
+}
+.fa.pull-left {
+  margin-right: .3em;
+}
+.fa.pull-right {
+  margin-left: .3em;
+}
+.fa-spin {
+  -webkit-animation: fa-spin 2s infinite linear;
+  animation: fa-spin 2s infinite linear;
+}
+.fa-pulse {
+  -webkit-animation: fa-spin 1s infinite steps(8);
+  animation: fa-spin 1s infinite steps(8);
+}
+@-webkit-keyframes fa-spin {
+  0% {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(359deg);
+    transform: rotate(359deg);
+  }
+}
+@keyframes fa-spin {
+  0% {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(359deg);
+    transform: rotate(359deg);
+  }
+}
+.fa-rotate-90 {
+  -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";
+  -webkit-transform: rotate(90deg);
+  -ms-transform: rotate(90deg);
+  transform: rotate(90deg);
+}
+.fa-rotate-180 {
+  -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";
+  -webkit-transform: rotate(180deg);
+  -ms-transform: rotate(180deg);
+  transform: rotate(180deg);
+}
+.fa-rotate-270 {
+  -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";
+  -webkit-transform: rotate(270deg);
+  -ms-transform: rotate(270deg);
+  transform: rotate(270deg);
+}
+.fa-flip-horizontal {
+  -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";
+  -webkit-transform: scale(-1, 1);
+  -ms-transform: scale(-1, 1);
+  transform: scale(-1, 1);
+}
+.fa-flip-vertical {
+  -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";
+  -webkit-transform: scale(1, -1);
+  -ms-transform: scale(1, -1);
+  transform: scale(1, -1);
+}
+:root .fa-rotate-90,
+:root .fa-rotate-180,
+:root .fa-rotate-270,
+:root .fa-flip-horizontal,
+:root .fa-flip-vertical {
+  filter: none;
+}
+.fa-stack {
+  position: relative;
+  display: inline-block;
+  width: 2em;
+  height: 2em;
+  line-height: 2em;
+  vertical-align: middle;
+}
+.fa-stack-1x,
+.fa-stack-2x {
+  position: absolute;
+  left: 0;
+  width: 100%;
+  text-align: center;
+}
+.fa-stack-1x {
+  line-height: inherit;
+}
+.fa-stack-2x {
+  font-size: 2em;
+}
+.fa-inverse {
+  color: #ffffff;
+}
+/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
+   readers do not read off random characters that represent icons */
+.fa-glass:before {
+  content: "\f000";
+}
+.fa-music:before {
+  content: "\f001";
+}
+.fa-search:before {
+  content: "\f002";
+}
+.fa-envelope-o:before {
+  content: "\f003";
+}
+.fa-heart:before {
+  content: "\f004";
+}
+.fa-star:before {
+  content: "\f005";
+}
+.fa-star-o:before {
+  content: "\f006";
+}
+.fa-user:before {
+  content: "\f007";
+}
+.fa-film:before {
+  content: "\f008";
+}
+.fa-th-large:before {
+  content: "\f009";
+}
+.fa-th:before {
+  content: "\f00a";
+}
+.fa-th-list:before {
+  content: "\f00b";
+}
+.fa-check:before {
+  content: "\f00c";
+}
+.fa-remove:before,
+.fa-close:before,
+.fa-times:before {
+  content: "\f00d";
+}
+.fa-search-plus:before {
+  content: "\f00e";
+}
+.fa-search-minus:before {
+  content: "\f010";
+}
+.fa-power-off:before {
+  content: "\f011";
+}
+.fa-signal:before {
+  content: "\f012";
+}
+.fa-gear:before,
+.fa-cog:before {
+  content: "\f013";
+}
+.fa-trash-o:before {
+  content: "\f014";
+}
+.fa-home:before {
+  content: "\f015";
+}
+.fa-file-o:before {
+  content: "\f016";
+}
+.fa-clock-o:before {
+  content: "\f017";
+}
+.fa-road:before {
+  content: "\f018";
+}
+.fa-download:before {
+  content: "\f019";
+}
+.fa-arrow-circle-o-down:before {
+  content: "\f01a";
+}
+.fa-arrow-circle-o-up:before {
+  content: "\f01b";
+}
+.fa-inbox:before {
+  content: "\f01c";
+}
+.fa-play-circle-o:before {
+  content: "\f01d";
+}
+.fa-rotate-right:before,
+.fa-repeat:before {
+  content: "\f01e";
+}
+.fa-refresh:before {
+  content: "\f021";
+}
+.fa-list-alt:before {
+  content: "\f022";
+}
+.fa-lock:before {
+  content: "\f023";
+}
+.fa-flag:before {
+  content: "\f024";
+}
+.fa-headphones:before {
+  content: "\f025";
+}
+.fa-volume-off:before {
+  content: "\f026";
+}
+.fa-volume-down:before {
+  content: "\f027";
+}
+.fa-volume-up:before {
+  content: "\f028";
+}
+.fa-qrcode:before {
+  content: "\f029";
+}
+.fa-barcode:before {
+  content: "\f02a";
+}
+.fa-tag:before {
+  content: "\f02b";
+}
+.fa-tags:before {
+  content: "\f02c";
+}
+.fa-book:before {
+  content: "\f02d";
+}
+.fa-bookmark:before {
+  content: "\f02e";
+}
+.fa-print:before {
+  content: "\f02f";
+}
+.fa-camera:before {
+  content: "\f030";
+}
+.fa-font:before {
+  content: "\f031";
+}
+.fa-bold:before {
+  content: "\f032";
+}
+.fa-italic:before {
+  content: "\f033";
+}
+.fa-text-height:before {
+  content: "\f034";
+}
+.fa-text-width:before {
+  content: "\f035";
+}
+.fa-align-left:before {
+  content: "\f036";
+}
+.fa-align-center:before {
+  content: "\f037";
+}
+.fa-align-right:before {
+  content: "\f038";
+}
+.fa-align-justify:before {
+  content: "\f039";
+}
+.fa-list:before {
+  content: "\f03a";
+}
+.fa-dedent:before,
+.fa-outdent:before {
+  content: "\f03b";
+}
+.fa-indent:before {
+  content: "\f03c";
+}
+.fa-video-camera:before {
+  content: "\f03d";
+}
+.fa-photo:before,
+.fa-image:before,
+.fa-picture-o:before {
+  content: "\f03e";
+}
+.fa-pencil:before {
+  content: "\f040";
+}
+.fa-map-marker:before {
+  content: "\f041";
+}
+.fa-adjust:before {
+  content: "\f042";
+}
+.fa-tint:before {
+  content: "\f043";
+}
+.fa-edit:before,
+.fa-pencil-square-o:before {
+  content: "\f044";
+}
+.fa-share-square-o:before {
+  content: "\f045";
+}
+.fa-check-square-o:before {
+  content: "\f046";
+}
+.fa-arrows:before {
+  content: "\f047";
+}
+.fa-step-backward:before {
+  content: "\f048";
+}
+.fa-fast-backward:before {
+  content: "\f049";
+}
+.fa-backward:before {
+  content: "\f04a";
+}
+.fa-play:before {
+  content: "\f04b";
+}
+.fa-pause:before {
+  content: "\f04c";
+}
+.fa-stop:before {
+  content: "\f04d";
+}
+.fa-forward:before {
+  content: "\f04e";
+}
+.fa-fast-forward:before {
+  content: "\f050";
+}
+.fa-step-forward:before {
+  content: "\f051";
+}
+.fa-eject:before {
+  content: "\f052";
+}
+.fa-chevron-left:before {
+  content: "\f053";
+}
+.fa-chevron-right:before {
+  content: "\f054";
+}
+.fa-plus-circle:before {
+  content: "\f055";
+}
+.fa-minus-circle:before {
+  content: "\f056";
+}
+.fa-times-circle:before {
+  content: "\f057";
+}
+.fa-check-circle:before {
+  content: "\f058";
+}
+.fa-question-circle:before {
+  content: "\f059";
+}
+.fa-info-circle:before {
+  content: "\f05a";
+}
+.fa-crosshairs:before {
+  content: "\f05b";
+}
+.fa-times-circle-o:before {
+  content: "\f05c";
+}
+.fa-check-circle-o:before {
+  content: "\f05d";
+}
+.fa-ban:before {
+  content: "\f05e";
+}
+.fa-arrow-left:before {
+  content: "\f060";
+}
+.fa-arrow-right:before {
+  content: "\f061";
+}
+.fa-arrow-up:before {
+  content: "\f062";
+}
+.fa-arrow-down:before {
+  content: "\f063";
+}
+.fa-mail-forward:before,
+.fa-share:before {
+  content: "\f064";
+}
+.fa-expand:before {
+  content: "\f065";
+}
+.fa-compress:before {
+  content: "\f066";
+}
+.fa-plus:before {
+  content: "\f067";
+}
+.fa-minus:before {
+  content: "\f068";
+}
+.fa-asterisk:before {
+  content: "\f069";
+}
+.fa-exclamation-circle:before {
+  content: "\f06a";
+}
+.fa-gift:before {
+  content: "\f06b";
+}
+.fa-leaf:before {
+  content: "\f06c";
+}
+.fa-fire:before {
+  content: "\f06d";
+}
+.fa-eye:before {
+  content: "\f06e";
+}
+.fa-eye-slash:before {
+  content: "\f070";
+}
+.fa-warning:before,
+.fa-exclamation-triangle:before {
+  content: "\f071";
+}
+.fa-plane:before {
+  content: "\f072";
+}
+.fa-calendar:before {
+  content: "\f073";
+}
+.fa-random:before {
+  content: "\f074";
+}
+.fa-comment:before {
+  content: "\f075";
+}
+.fa-magnet:before {
+  content: "\f076";
+}
+.fa-chevron-up:before {
+  content: "\f077";
+}
+.fa-chevron-down:before {
+  content: "\f078";
+}
+.fa-retweet:before {
+  content: "\f079";
+}
+.fa-shopping-cart:before {
+  content: "\f07a";
+}
+.fa-folder:before {
+  content: "\f07b";
+}
+.fa-folder-open:before {
+  content: "\f07c";
+}
+.fa-arrows-v:before {
+  content: "\f07d";
+}
+.fa-arrows-h:before {
+  content: "\f07e";
+}
+.fa-bar-chart-o:before,
+.fa-bar-chart:before {
+  content: "\f080";
+}
+.fa-twitter-square:before {
+  content: "\f081";
+}
+.fa-facebook-square:before {
+  content: "\f082";
+}
+.fa-camera-retro:before {
+  content: "\f083";
+}
+.fa-key:before {
+  content: "\f084";
+}
+.fa-gears:before,
+.fa-cogs:before {
+  content: "\f085";
+}
+.fa-comments:before {
+  content: "\f086";
+}
+.fa-thumbs-o-up:before {
+  content: "\f087";
+}
+.fa-thumbs-o-down:before {
+  content: "\f088";
+}
+.fa-star-half:before {
+  content: "\f089";
+}
+.fa-heart-o:before {
+  content: "\f08a";
+}
+.fa-sign-out:before {
+  content: "\f08b";
+}
+.fa-linkedin-square:before {
+  content: "\f08c";
+}
+.fa-thumb-tack:before {
+  content: "\f08d";
+}
+.fa-external-link:before {
+  content: "\f08e";
+}
+.fa-sign-in:before {
+  content: "\f090";
+}
+.fa-trophy:before {
+  content: "\f091";
+}
+.fa-github-square:before {
+  content: "\f092";
+}
+.fa-upload:before {
+  content: "\f093";
+}
+.fa-lemon-o:before {
+  content: "\f094";
+}
+.fa-phone:before {
+  content: "\f095";
+}
+.fa-square-o:before {
+  content: "\f096";
+}
+.fa-bookmark-o:before {
+  content: "\f097";
+}
+.fa-phone-square:before {
+  content: "\f098";
+}
+.fa-twitter:before {
+  content: "\f099";
+}
+.fa-facebook-f:before,
+.fa-facebook:before {
+  content: "\f09a";
+}
+.fa-github:before {
+  content: "\f09b";
+}
+.fa-unlock:before {
+  content: "\f09c";
+}
+.fa-credit-card:before {
+  content: "\f09d";
+}
+.fa-feed:before,
+.fa-rss:before {
+  content: "\f09e";
+}
+.fa-hdd-o:before {
+  content: "\f0a0";
+}
+.fa-bullhorn:before {
+  content: "\f0a1";
+}
+.fa-bell:before {
+  content: "\f0f3";
+}
+.fa-certificate:before {
+  content: "\f0a3";
+}
+.fa-hand-o-right:before {
+  content: "\f0a4";
+}
+.fa-hand-o-left:before {
+  content: "\f0a5";
+}
+.fa-hand-o-up:before {
+  content: "\f0a6";
+}
+.fa-hand-o-down:before {
+  content: "\f0a7";
+}
+.fa-arrow-circle-left:before {
+  content: "\f0a8";
+}
+.fa-arrow-circle-right:before {
+  content: "\f0a9";
+}
+.fa-arrow-circle-up:before {
+  content: "\f0aa";
+}
+.fa-arrow-circle-down:before {
+  content: "\f0ab";
+}
+.fa-globe:before {
+  content: "\f0ac";
+}
+.fa-wrench:before {
+  content: "\f0ad";
+}
+.fa-tasks:before {
+  content: "\f0ae";
+}
+.fa-filter:before {
+  content: "\f0b0";
+}
+.fa-briefcase:before {
+  content: "\f0b1";
+}
+.fa-arrows-alt:before {
+  content: "\f0b2";
+}
+.fa-group:before,
+.fa-users:before {
+  content: "\f0c0";
+}
+.fa-chain:before,
+.fa-link:before {
+  content: "\f0c1";
+}
+.fa-cloud:before {
+  content: "\f0c2";
+}
+.fa-flask:before {
+  content: "\f0c3";
+}
+.fa-cut:before,
+.fa-scissors:before {
+  content: "\f0c4";
+}
+.fa-copy:before,
+.fa-files-o:before {
+  content: "\f0c5";
+}
+.fa-paperclip:before {
+  content: "\f0c6";
+}
+.fa-save:before,
+.fa-floppy-o:before {
+  content: "\f0c7";
+}
+.fa-square:before {
+  content: "\f0c8";
+}
+.fa-navicon:before,
+.fa-reorder:before,
+.fa-bars:before {
+  content: "\f0c9";
+}
+.fa-list-ul:before {
+  content: "\f0ca";
+}
+.fa-list-ol:before {
+  content: "\f0cb";
+}
+.fa-strikethrough:before {
+  content: "\f0cc";
+}
+.fa-underline:before {
+  content: "\f0cd";
+}
+.fa-table:before {
+  content: "\f0ce";
+}
+.fa-magic:before {
+  content: "\f0d0";
+}
+.fa-truck:before {
+  content: "\f0d1";
+}
+.fa-pinterest:before {
+  content: "\f0d2";
+}
+.fa-pinterest-square:before {
+  content: "\f0d3";
+}
+.fa-google-plus-square:before {
+  content: "\f0d4";
+}
+.fa-google-plus:before {
+  content: "\f0d5";
+}
+.fa-money:before {
+  content: "\f0d6";
+}
+.fa-caret-down:before {
+  content: "\f0d7";
+}
+.fa-caret-up:before {
+  content: "\f0d8";
+}
+.fa-caret-left:before {
+  content: "\f0d9";
+}
+.fa-caret-right:before {
+  content: "\f0da";
+}
+.fa-columns:before {
+  content: "\f0db";
+}
+.fa-unsorted:before,
+.fa-sort:before {
+  content: "\f0dc";
+}
+.fa-sort-down:before,
+.fa-sort-desc:before {
+  content: "\f0dd";
+}
+.fa-sort-up:before,
+.fa-sort-asc:before {
+  content: "\f0de";
+}
+.fa-envelope:before {
+  content: "\f0e0";
+}
+.fa-linkedin:before {
+  content: "\f0e1";
+}
+.fa-rotate-left:before,
+.fa-undo:before {
+  content: "\f0e2";
+}
+.fa-legal:before,
+.fa-gavel:before {
+  content: "\f0e3";
+}
+.fa-dashboard:before,
+.fa-tachometer:before {
+  content: "\f0e4";
+}
+.fa-comment-o:before {
+  content: "\f0e5";
+}
+.fa-comments-o:before {
+  content: "\f0e6";
+}
+.fa-flash:before,
+.fa-bolt:before {
+  content: "\f0e7";
+}
+.fa-sitemap:before {
+  content: "\f0e8";
+}
+.fa-umbrella:before {
+  content: "\f0e9";
+}
+.fa-paste:before,
+.fa-clipboard:before {
+  content: "\f0ea";
+}
+.fa-lightbulb-o:before {
+  content: "\f0eb";
+}
+.fa-exchange:before {
+  content: "\f0ec";
+}
+.fa-cloud-download:before {
+  content: "\f0ed";
+}
+.fa-cloud-upload:before {
+  content: "\f0ee";
+}
+.fa-user-md:before {
+  content: "\f0f0";
+}
+.fa-stethoscope:before {
+  content: "\f0f1";
+}
+.fa-suitcase:before {
+  content: "\f0f2";
+}
+.fa-bell-o:before {
+  content: "\f0a2";
+}
+.fa-coffee:before {
+  content: "\f0f4";
+}
+.fa-cutlery:before {
+  content: "\f0f5";
+}
+.fa-file-text-o:before {
+  content: "\f0f6";
+}
+.fa-building-o:before {
+  content: "\f0f7";
+}
+.fa-hospital-o:before {
+  content: "\f0f8";
+}
+.fa-ambulance:before {
+  content: "\f0f9";
+}
+.fa-medkit:before {
+  content: "\f0fa";
+}
+.fa-fighter-jet:before {
+  content: "\f0fb";
+}
+.fa-beer:before {
+  content: "\f0fc";
+}
+.fa-h-square:before {
+  content: "\f0fd";
+}
+.fa-plus-square:before {
+  content: "\f0fe";
+}
+.fa-angle-double-left:before {
+  content: "\f100";
+}
+.fa-angle-double-right:before {
+  content: "\f101";
+}
+.fa-angle-double-up:before {
+  content: "\f102";
+}
+.fa-angle-double-down:before {
+  content: "\f103";
+}
+.fa-angle-left:before {
+  content: "\f104";
+}
+.fa-angle-right:before {
+  content: "\f105";
+}
+.fa-angle-up:before {
+  content: "\f106";
+}
+.fa-angle-down:before {
+  content: "\f107";
+}
+.fa-desktop:before {
+  content: "\f108";
+}
+.fa-laptop:before {
+  content: "\f109";
+}
+.fa-tablet:before {
+  content: "\f10a";
+}
+.fa-mobile-phone:before,
+.fa-mobile:before {
+  content: "\f10b";
+}
+.fa-circle-o:before {
+  content: "\f10c";
+}
+.fa-quote-left:before {
+  content: "\f10d";
+}
+.fa-quote-right:before {
+  content: "\f10e";
+}
+.fa-spinner:before {
+  content: "\f110";
+}
+.fa-circle:before {
+  content: "\f111";
+}
+.fa-mail-reply:before,
+.fa-reply:before {
+  content: "\f112";
+}
+.fa-github-alt:before {
+  content: "\f113";
+}
+.fa-folder-o:before {
+  content: "\f114";
+}
+.fa-folder-open-o:before {
+  content: "\f115";
+}
+.fa-smile-o:before {
+  content: "\f118";
+}
+.fa-frown-o:before {
+  content: "\f119";
+}
+.fa-meh-o:before {
+  content: "\f11a";
+}
+.fa-gamepad:before {
+  content: "\f11b";
+}
+.fa-keyboard-o:before {
+  content: "\f11c";
+}
+.fa-flag-o:before {
+  content: "\f11d";
+}
+.fa-flag-checkered:before {
+  content: "\f11e";
+}
+.fa-terminal:before {
+  content: "\f120";
+}
+.fa-code:before {
+  content: "\f121";
+}
+.fa-mail-reply-all:before,
+.fa-reply-all:before {
+  content: "\f122";
+}
+.fa-star-half-empty:before,
+.fa-star-half-full:before,
+.fa-star-half-o:before {
+  content: "\f123";
+}
+.fa-location-arrow:before {
+  content: "\f124";
+}
+.fa-crop:before {
+  content: "\f125";
+}
+.fa-code-fork:before {
+  content: "\f126";
+}
+.fa-unlink:before,
+.fa-chain-broken:before {
+  content: "\f127";
+}
+.fa-question:before {
+  content: "\f128";
+}
+.fa-info:before {
+  content: "\f129";
+}
+.fa-exclamation:before {
+  content: "\f12a";
+}
+.fa-superscript:before {
+  content: "\f12b";
+}
+.fa-subscript:before {
+  content: "\f12c";
+}
+.fa-eraser:before {
+  content: "\f12d";
+}
+.fa-puzzle-piece:before {
+  content: "\f12e";
+}
+.fa-microphone:before {
+  content: "\f130";
+}
+.fa-microphone-slash:before {
+  content: "\f131";
+}
+.fa-shield:before {
+  content: "\f132";
+}
+.fa-calendar-o:before {
+  content: "\f133";
+}
+.fa-fire-extinguisher:before {
+  content: "\f134";
+}
+.fa-rocket:before {
+  content: "\f135";
+}
+.fa-maxcdn:before {
+  content: "\f136";
+}
+.fa-chevron-circle-left:before {
+  content: "\f137";
+}
+.fa-chevron-circle-right:before {
+  content: "\f138";
+}
+.fa-chevron-circle-up:before {
+  content: "\f139";
+}
+.fa-chevron-circle-down:before {
+  content: "\f13a";
+}
+.fa-html5:before {
+  content: "\f13b";
+}
+.fa-css3:before {
+  content: "\f13c";
+}
+.fa-anchor:before {
+  content: "\f13d";
+}
+.fa-unlock-alt:before {
+  content: "\f13e";
+}
+.fa-bullseye:before {
+  content: "\f140";
+}
+.fa-ellipsis-h:before {
+  content: "\f141";
+}
+.fa-ellipsis-v:before {
+  content: "\f142";
+}
+.fa-rss-square:before {
+  content: "\f143";
+}
+.fa-play-circle:before {
+  content: "\f144";
+}
+.fa-ticket:before {
+  content: "\f145";
+}
+.fa-minus-square:before {
+  content: "\f146";
+}
+.fa-minus-square-o:before {
+  content: "\f147";
+}
+.fa-level-up:before {
+  content: "\f148";
+}
+.fa-level-down:before {
+  content: "\f149";
+}
+.fa-check-square:before {
+  content: "\f14a";
+}
+.fa-pencil-square:before {
+  content: "\f14b";
+}
+.fa-external-link-square:before {
+  content: "\f14c";
+}
+.fa-share-square:before {
+  content: "\f14d";
+}
+.fa-compass:before {
+  content: "\f14e";
+}
+.fa-toggle-down:before,
+.fa-caret-square-o-down:before {
+  content: "\f150";
+}
+.fa-toggle-up:before,
+.fa-caret-square-o-up:before {
+  content: "\f151";
+}
+.fa-toggle-right:before,
+.fa-caret-square-o-right:before {
+  content: "\f152";
+}
+.fa-euro:before,
+.fa-eur:before {
+  content: "\f153";
+}
+.fa-gbp:before {
+  content: "\f154";
+}
+.fa-dollar:before,
+.fa-usd:before {
+  content: "\f155";
+}
+.fa-rupee:before,
+.fa-inr:before {
+  content: "\f156";
+}
+.fa-cny:before,
+.fa-rmb:before,
+.fa-yen:before,
+.fa-jpy:before {
+  content: "\f157";
+}
+.fa-ruble:before,
+.fa-rouble:before,
+.fa-rub:before {
+  content: "\f158";
+}
+.fa-won:before,
+.fa-krw:before {
+  content: "\f159";
+}
+.fa-bitcoin:before,
+.fa-btc:before {
+  content: "\f15a";
+}
+.fa-file:before {
+  content: "\f15b";
+}
+.fa-file-text:before {
+  content: "\f15c";
+}
+.fa-sort-alpha-asc:before {
+  content: "\f15d";
+}
+.fa-sort-alpha-desc:before {
+  content: "\f15e";
+}
+.fa-sort-amount-asc:before {
+  content: "\f160";
+}
+.fa-sort-amount-desc:before {
+  content: "\f161";
+}
+.fa-sort-numeric-asc:before {
+  content: "\f162";
+}
+.fa-sort-numeric-desc:before {
+  content: "\f163";
+}
+.fa-thumbs-up:before {
+  content: "\f164";
+}
+.fa-thumbs-down:before {
+  content: "\f165";
+}
+.fa-youtube-square:before {
+  content: "\f166";
+}
+.fa-youtube:before {
+  content: "\f167";
+}
+.fa-xing:before {
+  content: "\f168";
+}
+.fa-xing-square:before {
+  content: "\f169";
+}
+.fa-youtube-play:before {
+  content: "\f16a";
+}
+.fa-dropbox:before {
+  content: "\f16b";
+}
+.fa-stack-overflow:before {
+  content: "\f16c";
+}
+.fa-instagram:before {
+  content: "\f16d";
+}
+.fa-flickr:before {
+  content: "\f16e";
+}
+.fa-adn:before {
+  content: "\f170";
+}
+.fa-bitbucket:before {
+  content: "\f171";
+}
+.fa-bitbucket-square:before {
+  content: "\f172";
+}
+.fa-tumblr:before {
+  content: "\f173";
+}
+.fa-tumblr-square:before {
+  content: "\f174";
+}
+.fa-long-arrow-down:before {
+  content: "\f175";
+}
+.fa-long-arrow-up:before {
+  content: "\f176";
+}
+.fa-long-arrow-left:before {
+  content: "\f177";
+}
+.fa-long-arrow-right:before {
+  content: "\f178";
+}
+.fa-apple:before {
+  content: "\f179";
+}
+.fa-windows:before {
+  content: "\f17a";
+}
+.fa-android:before {
+  content: "\f17b";
+}
+.fa-linux:before {
+  content: "\f17c";
+}
+.fa-dribbble:before {
+  content: "\f17d";
+}
+.fa-skype:before {
+  content: "\f17e";
+}
+.fa-foursquare:before {
+  content: "\f180";
+}
+.fa-trello:before {
+  content: "\f181";
+}
+.fa-female:before {
+  content: "\f182";
+}
+.fa-male:before {
+  content: "\f183";
+}
+.fa-gittip:before,
+.fa-gratipay:before {
+  content: "\f184";
+}
+.fa-sun-o:before {
+  content: "\f185";
+}
+.fa-moon-o:before {
+  content: "\f186";
+}
+.fa-archive:before {
+  content: "\f187";
+}
+.fa-bug:before {
+  content: "\f188";
+}
+.fa-vk:before {
+  content: "\f189";
+}
+.fa-weibo:before {
+  content: "\f18a";
+}
+.fa-renren:before {
+  content: "\f18b";
+}
+.fa-pagelines:before {
+  content: "\f18c";
+}
+.fa-stack-exchange:before {
+  content: "\f18d";
+}
+.fa-arrow-circle-o-right:before {
+  content: "\f18e";
+}
+.fa-arrow-circle-o-left:before {
+  content: "\f190";
+}
+.fa-toggle-left:before,
+.fa-caret-square-o-left:before {
+  content: "\f191";
+}
+.fa-dot-circle-o:before {
+  content: "\f192";
+}
+.fa-wheelchair:before {
+  content: "\f193";
+}
+.fa-vimeo-square:before {
+  content: "\f194";
+}
+.fa-turkish-lira:before,
+.fa-try:before {
+  content: "\f195";
+}
+.fa-plus-square-o:before {
+  content: "\f196";
+}
+.fa-space-shuttle:before {
+  content: "\f197";
+}
+.fa-slack:before {
+  content: "\f198";
+}
+.fa-envelope-square:before {
+  content: "\f199";
+}
+.fa-wordpress:before {
+  content: "\f19a";
+}
+.fa-openid:before {
+  content: "\f19b";
+}
+.fa-institution:before,
+.fa-bank:before,
+.fa-university:before {
+  content: "\f19c";
+}
+.fa-mortar-board:before,
+.fa-graduation-cap:before {
+  content: "\f19d";
+}
+.fa-yahoo:before {
+  content: "\f19e";
+}
+.fa-google:before {
+  content: "\f1a0";
+}
+.fa-reddit:before {
+  content: "\f1a1";
+}
+.fa-reddit-square:before {
+  content: "\f1a2";
+}
+.fa-stumbleupon-circle:before {
+  content: "\f1a3";
+}
+.fa-stumbleupon:before {
+  content: "\f1a4";
+}
+.fa-delicious:before {
+  content: "\f1a5";
+}
+.fa-digg:before {
+  content: "\f1a6";
+}
+.fa-pied-piper-pp:before {
+  content: "\f1a7";
+}
+.fa-pied-piper-alt:before {
+  content: "\f1a8";
+}
+.fa-drupal:before {
+  content: "\f1a9";
+}
+.fa-joomla:before {
+  content: "\f1aa";
+}
+.fa-language:before {
+  content: "\f1ab";
+}
+.fa-fax:before {
+  content: "\f1ac";
+}
+.fa-building:before {
+  content: "\f1ad";
+}
+.fa-child:before {
+  content: "\f1ae";
+}
+.fa-paw:before {
+  content: "\f1b0";
+}
+.fa-spoon:before {
+  content: "\f1b1";
+}
+.fa-cube:before {
+  content: "\f1b2";
+}
+.fa-cubes:before {
+  content: "\f1b3";
+}
+.fa-behance:before {
+  content: "\f1b4";
+}
+.fa-behance-square:before {
+  content: "\f1b5";
+}
+.fa-steam:before {
+  content: "\f1b6";
+}
+.fa-steam-square:before {
+  content: "\f1b7";
+}
+.fa-recycle:before {
+  content: "\f1b8";
+}
+.fa-automobile:before,
+.fa-car:before {
+  content: "\f1b9";
+}
+.fa-cab:before,
+.fa-taxi:before {
+  content: "\f1ba";
+}
+.fa-tree:before {
+  content: "\f1bb";
+}
+.fa-spotify:before {
+  content: "\f1bc";
+}
+.fa-deviantart:before {
+  content: "\f1bd";
+}
+.fa-soundcloud:before {
+  content: "\f1be";
+}
+.fa-database:before {
+  content: "\f1c0";
+}
+.fa-file-pdf-o:before {
+  content: "\f1c1";
+}
+.fa-file-word-o:before {
+  content: "\f1c2";
+}
+.fa-file-excel-o:before {
+  content: "\f1c3";
+}
+.fa-file-powerpoint-o:before {
+  content: "\f1c4";
+}
+.fa-file-photo-o:before,
+.fa-file-picture-o:before,
+.fa-file-image-o:before {
+  content: "\f1c5";
+}
+.fa-file-zip-o:before,
+.fa-file-archive-o:before {
+  content: "\f1c6";
+}
+.fa-file-sound-o:before,
+.fa-file-audio-o:before {
+  content: "\f1c7";
+}
+.fa-file-movie-o:before,
+.fa-file-video-o:before {
+  content: "\f1c8";
+}
+.fa-file-code-o:before {
+  content: "\f1c9";
+}
+.fa-vine:before {
+  content: "\f1ca";
+}
+.fa-codepen:before {
+  content: "\f1cb";
+}
+.fa-jsfiddle:before {
+  content: "\f1cc";
+}
+.fa-life-bouy:before,
+.fa-life-buoy:before,
+.fa-life-saver:before,
+.fa-support:before,
+.fa-life-ring:before {
+  content: "\f1cd";
+}
+.fa-circle-o-notch:before {
+  content: "\f1ce";
+}
+.fa-ra:before,
+.fa-resistance:before,
+.fa-rebel:before {
+  content: "\f1d0";
+}
+.fa-ge:before,
+.fa-empire:before {
+  content: "\f1d1";
+}
+.fa-git-square:before {
+  content: "\f1d2";
+}
+.fa-git:before {
+  content: "\f1d3";
+}
+.fa-y-combinator-square:before,
+.fa-yc-square:before,
+.fa-hacker-news:before {
+  content: "\f1d4";
+}
+.fa-tencent-weibo:before {
+  content: "\f1d5";
+}
+.fa-qq:before {
+  content: "\f1d6";
+}
+.fa-wechat:before,
+.fa-weixin:before {
+  content: "\f1d7";
+}
+.fa-send:before,
+.fa-paper-plane:before {
+  content: "\f1d8";
+}
+.fa-send-o:before,
+.fa-paper-plane-o:before {
+  content: "\f1d9";
+}
+.fa-history:before {
+  content: "\f1da";
+}
+.fa-circle-thin:before {
+  content: "\f1db";
+}
+.fa-header:before {
+  content: "\f1dc";
+}
+.fa-paragraph:before {
+  content: "\f1dd";
+}
+.fa-sliders:before {
+  content: "\f1de";
+}
+.fa-share-alt:before {
+  content: "\f1e0";
+}
+.fa-share-alt-square:before {
+  content: "\f1e1";
+}
+.fa-bomb:before {
+  content: "\f1e2";
+}
+.fa-soccer-ball-o:before,
+.fa-futbol-o:before {
+  content: "\f1e3";
+}
+.fa-tty:before {
+  content: "\f1e4";
+}
+.fa-binoculars:before {
+  content: "\f1e5";
+}
+.fa-plug:before {
+  content: "\f1e6";
+}
+.fa-slideshare:before {
+  content: "\f1e7";
+}
+.fa-twitch:before {
+  content: "\f1e8";
+}
+.fa-yelp:before {
+  content: "\f1e9";
+}
+.fa-newspaper-o:before {
+  content: "\f1ea";
+}
+.fa-wifi:before {
+  content: "\f1eb";
+}
+.fa-calculator:before {
+  content: "\f1ec";
+}
+.fa-paypal:before {
+  content: "\f1ed";
+}
+.fa-google-wallet:before {
+  content: "\f1ee";
+}
+.fa-cc-visa:before {
+  content: "\f1f0";
+}
+.fa-cc-mastercard:before {
+  content: "\f1f1";
+}
+.fa-cc-discover:before {
+  content: "\f1f2";
+}
+.fa-cc-amex:before {
+  content: "\f1f3";
+}
+.fa-cc-paypal:before {
+  content: "\f1f4";
+}
+.fa-cc-stripe:before {
+  content: "\f1f5";
+}
+.fa-bell-slash:before {
+  content: "\f1f6";
+}
+.fa-bell-slash-o:before {
+  content: "\f1f7";
+}
+.fa-trash:before {
+  content: "\f1f8";
+}
+.fa-copyright:before {
+  content: "\f1f9";
+}
+.fa-at:before {
+  content: "\f1fa";
+}
+.fa-eyedropper:before {
+  content: "\f1fb";
+}
+.fa-paint-brush:before {
+  content: "\f1fc";
+}
+.fa-birthday-cake:before {
+  content: "\f1fd";
+}
+.fa-area-chart:before {
+  content: "\f1fe";
+}
+.fa-pie-chart:before {
+  content: "\f200";
+}
+.fa-line-chart:before {
+  content: "\f201";
+}
+.fa-lastfm:before {
+  content: "\f202";
+}
+.fa-lastfm-square:before {
+  content: "\f203";
+}
+.fa-toggle-off:before {
+  content: "\f204";
+}
+.fa-toggle-on:before {
+  content: "\f205";
+}
+.fa-bicycle:before {
+  content: "\f206";
+}
+.fa-bus:before {
+  content: "\f207";
+}
+.fa-ioxhost:before {
+  content: "\f208";
+}
+.fa-angellist:before {
+  content: "\f209";
+}
+.fa-cc:before {
+  content: "\f20a";
+}
+.fa-shekel:before,
+.fa-sheqel:before,
+.fa-ils:before {
+  content: "\f20b";
+}
+.fa-meanpath:before {
+  content: "\f20c";
+}
+.fa-buysellads:before {
+  content: "\f20d";
+}
+.fa-connectdevelop:before {
+  content: "\f20e";
+}
+.fa-dashcube:before {
+  content: "\f210";
+}
+.fa-forumbee:before {
+  content: "\f211";
+}
+.fa-leanpub:before {
+  content: "\f212";
+}
+.fa-sellsy:before {
+  content: "\f213";
+}
+.fa-shirtsinbulk:before {
+  content: "\f214";
+}
+.fa-simplybuilt:before {
+  content: "\f215";
+}
+.fa-skyatlas:before {
+  content: "\f216";
+}
+.fa-cart-plus:before {
+  content: "\f217";
+}
+.fa-cart-arrow-down:before {
+  content: "\f218";
+}
+.fa-diamond:before {
+  content: "\f219";
+}
+.fa-ship:before {
+  content: "\f21a";
+}
+.fa-user-secret:before {
+  content: "\f21b";
+}
+.fa-motorcycle:before {
+  content: "\f21c";
+}
+.fa-street-view:before {
+  content: "\f21d";
+}
+.fa-heartbeat:before {
+  content: "\f21e";
+}
+.fa-venus:before {
+  content: "\f221";
+}
+.fa-mars:before {
+  content: "\f222";
+}
+.fa-mercury:before {
+  content: "\f223";
+}
+.fa-intersex:before,
+.fa-transgender:before {
+  content: "\f224";
+}
+.fa-transgender-alt:before {
+  content: "\f225";
+}
+.fa-venus-double:before {
+  content: "\f226";
+}
+.fa-mars-double:before {
+  content: "\f227";
+}
+.fa-venus-mars:before {
+  content: "\f228";
+}
+.fa-mars-stroke:before {
+  content: "\f229";
+}
+.fa-mars-stroke-v:before {
+  content: "\f22a";
+}
+.fa-mars-stroke-h:before {
+  content: "\f22b";
+}
+.fa-neuter:before {
+  content: "\f22c";
+}
+.fa-genderless:before {
+  content: "\f22d";
+}
+.fa-facebook-official:before {
+  content: "\f230";
+}
+.fa-pinterest-p:before {
+  content: "\f231";
+}
+.fa-whatsapp:before {
+  content: "\f232";
+}
+.fa-server:before {
+  content: "\f233";
+}
+.fa-user-plus:before {
+  content: "\f234";
+}
+.fa-user-times:before {
+  content: "\f235";
+}
+.fa-hotel:before,
+.fa-bed:before {
+  content: "\f236";
+}
+.fa-viacoin:before {
+  content: "\f237";
+}
+.fa-train:before {
+  content: "\f238";
+}
+.fa-subway:before {
+  content: "\f239";
+}
+.fa-medium:before {
+  content: "\f23a";
+}
+.fa-yc:before,
+.fa-y-combinator:before {
+  content: "\f23b";
+}
+.fa-optin-monster:before {
+  content: "\f23c";
+}
+.fa-opencart:before {
+  content: "\f23d";
+}
+.fa-expeditedssl:before {
+  content: "\f23e";
+}
+.fa-battery-4:before,
+.fa-battery:before,
+.fa-battery-full:before {
+  content: "\f240";
+}
+.fa-battery-3:before,
+.fa-battery-three-quarters:before {
+  content: "\f241";
+}
+.fa-battery-2:before,
+.fa-battery-half:before {
+  content: "\f242";
+}
+.fa-battery-1:before,
+.fa-battery-quarter:before {
+  content: "\f243";
+}
+.fa-battery-0:before,
+.fa-battery-empty:before {
+  content: "\f244";
+}
+.fa-mouse-pointer:before {
+  content: "\f245";
+}
+.fa-i-cursor:before {
+  content: "\f246";
+}
+.fa-object-group:before {
+  content: "\f247";
+}
+.fa-object-ungroup:before {
+  content: "\f248";
+}
+.fa-sticky-note:before {
+  content: "\f249";
+}
+.fa-sticky-note-o:before {
+  content: "\f24a";
+}
+.fa-cc-jcb:before {
+  content: "\f24b";
+}
+.fa-cc-diners-club:before {
+  content: "\f24c";
+}
+.fa-clone:before {
+  content: "\f24d";
+}
+.fa-balance-scale:before {
+  content: "\f24e";
+}
+.fa-hourglass-o:before {
+  content: "\f250";
+}
+.fa-hourglass-1:before,
+.fa-hourglass-start:before {
+  content: "\f251";
+}
+.fa-hourglass-2:before,
+.fa-hourglass-half:before {
+  content: "\f252";
+}
+.fa-hourglass-3:before,
+.fa-hourglass-end:before {
+  content: "\f253";
+}
+.fa-hourglass:before {
+  content: "\f254";
+}
+.fa-hand-grab-o:before,
+.fa-hand-rock-o:before {
+  content: "\f255";
+}
+.fa-hand-stop-o:before,
+.fa-hand-paper-o:before {
+  content: "\f256";
+}
+.fa-hand-scissors-o:before {
+  content: "\f257";
+}
+.fa-hand-lizard-o:before {
+  content: "\f258";
+}
+.fa-hand-spock-o:before {
+  content: "\f259";
+}
+.fa-hand-pointer-o:before {
+  content: "\f25a";
+}
+.fa-hand-peace-o:before {
+  content: "\f25b";
+}
+.fa-trademark:before {
+  content: "\f25c";
+}
+.fa-registered:before {
+  content: "\f25d";
+}
+.fa-creative-commons:before {
+  content: "\f25e";
+}
+.fa-gg:before {
+  content: "\f260";
+}
+.fa-gg-circle:before {
+  content: "\f261";
+}
+.fa-tripadvisor:before {
+  content: "\f262";
+}
+.fa-odnoklassniki:before {
+  content: "\f263";
+}
+.fa-odnoklassniki-square:before {
+  content: "\f264";
+}
+.fa-get-pocket:before {
+  content: "\f265";
+}
+.fa-wikipedia-w:before {
+  content: "\f266";
+}
+.fa-safari:before {
+  content: "\f267";
+}
+.fa-chrome:before {
+  content: "\f268";
+}
+.fa-firefox:before {
+  content: "\f269";
+}
+.fa-opera:before {
+  content: "\f26a";
+}
+.fa-internet-explorer:before {
+  content: "\f26b";
+}
+.fa-tv:before,
+.fa-television:before {
+  content: "\f26c";
+}
+.fa-contao:before {
+  content: "\f26d";
+}
+.fa-500px:before {
+  content: "\f26e";
+}
+.fa-amazon:before {
+  content: "\f270";
+}
+.fa-calendar-plus-o:before {
+  content: "\f271";
+}
+.fa-calendar-minus-o:before {
+  content: "\f272";
+}
+.fa-calendar-times-o:before {
+  content: "\f273";
+}
+.fa-calendar-check-o:before {
+  content: "\f274";
+}
+.fa-industry:before {
+  content: "\f275";
+}
+.fa-map-pin:before {
+  content: "\f276";
+}
+.fa-map-signs:before {
+  content: "\f277";
+}
+.fa-map-o:before {
+  content: "\f278";
+}
+.fa-map:before {
+  content: "\f279";
+}
+.fa-commenting:before {
+  content: "\f27a";
+}
+.fa-commenting-o:before {
+  content: "\f27b";
+}
+.fa-houzz:before {
+  content: "\f27c";
+}
+.fa-vimeo:before {
+  content: "\f27d";
+}
+.fa-black-tie:before {
+  content: "\f27e";
+}
+.fa-fonticons:before {
+  content: "\f280";
+}
+.fa-reddit-alien:before {
+  content: "\f281";
+}
+.fa-edge:before {
+  content: "\f282";
+}
+.fa-credit-card-alt:before {
+  content: "\f283";
+}
+.fa-codiepie:before {
+  content: "\f284";
+}
+.fa-modx:before {
+  content: "\f285";
+}
+.fa-fort-awesome:before {
+  content: "\f286";
+}
+.fa-usb:before {
+  content: "\f287";
+}
+.fa-product-hunt:before {
+  content: "\f288";
+}
+.fa-mixcloud:before {
+  content: "\f289";
+}
+.fa-scribd:before {
+  content: "\f28a";
+}
+.fa-pause-circle:before {
+  content: "\f28b";
+}
+.fa-pause-circle-o:before {
+  content: "\f28c";
+}
+.fa-stop-circle:before {
+  content: "\f28d";
+}
+.fa-stop-circle-o:before {
+  content: "\f28e";
+}
+.fa-shopping-bag:before {
+  content: "\f290";
+}
+.fa-shopping-basket:before {
+  content: "\f291";
+}
+.fa-hashtag:before {
+  content: "\f292";
+}
+.fa-bluetooth:before {
+  content: "\f293";
+}
+.fa-bluetooth-b:before {
+  content: "\f294";
+}
+.fa-percent:before {
+  content: "\f295";
+}
+.fa-gitlab:before {
+  content: "\f296";
+}
+.fa-wpbeginner:before {
+  content: "\f297";
+}
+.fa-wpforms:before {
+  content: "\f298";
+}
+.fa-envira:before {
+  content: "\f299";
+}
+.fa-universal-access:before {
+  content: "\f29a";
+}
+.fa-wheelchair-alt:before {
+  content: "\f29b";
+}
+.fa-question-circle-o:before {
+  content: "\f29c";
+}
+.fa-blind:before {
+  content: "\f29d";
+}
+.fa-audio-description:before {
+  content: "\f29e";
+}
+.fa-volume-control-phone:before {
+  content: "\f2a0";
+}
+.fa-braille:before {
+  content: "\f2a1";
+}
+.fa-assistive-listening-systems:before {
+  content: "\f2a2";
+}
+.fa-asl-interpreting:before,
+.fa-american-sign-language-interpreting:before {
+  content: "\f2a3";
+}
+.fa-deafness:before,
+.fa-hard-of-hearing:before,
+.fa-deaf:before {
+  content: "\f2a4";
+}
+.fa-glide:before {
+  content: "\f2a5";
+}
+.fa-glide-g:before {
+  content: "\f2a6";
+}
+.fa-signing:before,
+.fa-sign-language:before {
+  content: "\f2a7";
+}
+.fa-low-vision:before {
+  content: "\f2a8";
+}
+.fa-viadeo:before {
+  content: "\f2a9";
+}
+.fa-viadeo-square:before {
+  content: "\f2aa";
+}
+.fa-snapchat:before {
+  content: "\f2ab";
+}
+.fa-snapchat-ghost:before {
+  content: "\f2ac";
+}
+.fa-snapchat-square:before {
+  content: "\f2ad";
+}
+.fa-pied-piper:before {
+  content: "\f2ae";
+}
+.fa-first-order:before {
+  content: "\f2b0";
+}
+.fa-yoast:before {
+  content: "\f2b1";
+}
+.fa-themeisle:before {
+  content: "\f2b2";
+}
+.fa-google-plus-circle:before,
+.fa-google-plus-official:before {
+  content: "\f2b3";
+}
+.fa-fa:before,
+.fa-font-awesome:before {
+  content: "\f2b4";
+}
+.fa-handshake-o:before {
+  content: "\f2b5";
+}
+.fa-envelope-open:before {
+  content: "\f2b6";
+}
+.fa-envelope-open-o:before {
+  content: "\f2b7";
+}
+.fa-linode:before {
+  content: "\f2b8";
+}
+.fa-address-book:before {
+  content: "\f2b9";
+}
+.fa-address-book-o:before {
+  content: "\f2ba";
+}
+.fa-vcard:before,
+.fa-address-card:before {
+  content: "\f2bb";
+}
+.fa-vcard-o:before,
+.fa-address-card-o:before {
+  content: "\f2bc";
+}
+.fa-user-circle:before {
+  content: "\f2bd";
+}
+.fa-user-circle-o:before {
+  content: "\f2be";
+}
+.fa-user-o:before {
+  content: "\f2c0";
+}
+.fa-id-badge:before {
+  content: "\f2c1";
+}
+.fa-drivers-license:before,
+.fa-id-card:before {
+  content: "\f2c2";
+}
+.fa-drivers-license-o:before,
+.fa-id-card-o:before {
+  content: "\f2c3";
+}
+.fa-quora:before {
+  content: "\f2c4";
+}
+.fa-free-code-camp:before {
+  content: "\f2c5";
+}
+.fa-telegram:before {
+  content: "\f2c6";
+}
+.fa-thermometer-4:before,
+.fa-thermometer:before,
+.fa-thermometer-full:before {
+  content: "\f2c7";
+}
+.fa-thermometer-3:before,
+.fa-thermometer-three-quarters:before {
+  content: "\f2c8";
+}
+.fa-thermometer-2:before,
+.fa-thermometer-half:before {
+  content: "\f2c9";
+}
+.fa-thermometer-1:before,
+.fa-thermometer-quarter:before {
+  content: "\f2ca";
+}
+.fa-thermometer-0:before,
+.fa-thermometer-empty:before {
+  content: "\f2cb";
+}
+.fa-shower:before {
+  content: "\f2cc";
+}
+.fa-bathtub:before,
+.fa-s15:before,
+.fa-bath:before {
+  content: "\f2cd";
+}
+.fa-podcast:before {
+  content: "\f2ce";
+}
+.fa-window-maximize:before {
+  content: "\f2d0";
+}
+.fa-window-minimize:before {
+  content: "\f2d1";
+}
+.fa-window-restore:before {
+  content: "\f2d2";
+}
+.fa-times-rectangle:before,
+.fa-window-close:before {
+  content: "\f2d3";
+}
+.fa-times-rectangle-o:before,
+.fa-window-close-o:before {
+  content: "\f2d4";
+}
+.fa-bandcamp:before {
+  content: "\f2d5";
+}
+.fa-grav:before {
+  content: "\f2d6";
+}
+.fa-etsy:before {
+  content: "\f2d7";
+}
+.fa-imdb:before {
+  content: "\f2d8";
+}
+.fa-ravelry:before {
+  content: "\f2d9";
+}
+.fa-eercast:before {
+  content: "\f2da";
+}
+.fa-microchip:before {
+  content: "\f2db";
+}
+.fa-snowflake-o:before {
+  content: "\f2dc";
+}
+.fa-superpowers:before {
+  content: "\f2dd";
+}
+.fa-wpexplorer:before {
+  content: "\f2de";
+}
+.fa-meetup:before {
+  content: "\f2e0";
+}
+.sr-only {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  padding: 0;
+  margin: -1px;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+}
+.sr-only-focusable:active,
+.sr-only-focusable:focus {
+  position: static;
+  width: auto;
+  height: auto;
+  margin: 0;
+  overflow: visible;
+  clip: auto;
+}
diff --git a/docs/site/home/css/fonts.css b/docs/site/home/css/fonts.css
new file mode 100644
index 0000000..9a63156
--- /dev/null
+++ b/docs/site/home/css/fonts.css
@@ -0,0 +1,180 @@
+/* cyrillic-ext */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 400;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 400;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* vietnamese */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 400;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 400;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 400;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* cyrillic-ext */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 500;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 500;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* vietnamese */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 500;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 500;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 500;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* cyrillic-ext */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 600;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 600;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* vietnamese */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 600;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 600;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 600;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* cyrillic-ext */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 700;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
+}
+/* cyrillic */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 700;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
+}
+/* vietnamese */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 700;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 700;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Raleway';
+  font-style: normal;
+  font-weight: 700;
+  font-display: swap;
+  src: url(../fonts/raleway.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
diff --git a/docs/site/home/download.html b/docs/site/home/download.html
index 773a625..bd189db 100644
--- a/docs/site/home/download.html
+++ b/docs/site/home/download.html
@@ -19,118 +19,166 @@
         <meta http-equiv="X-UA-Compatible" content="IE=edge">
         <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
         <link href="img/favicon.png" rel="shortcut icon" />
-        <title>Apache TinkerPop</title>
+        <title>Apache TinkerPop: Downloads</title>
         <meta name="description" content="">
         <meta name="keywords" content="">
-        <link href="css/bootstrap.min.css" rel="stylesheet"><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" integrity="sha512-5A8nwdMOWrSz20fDsjczgUidUBR8liPYU+WymTZP1lmY9G6Oc7HlZv156XqnsgNUzTyMefFTcsFH/tnJE/+xBg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
+        <link href="css/bootstrap.min.css" rel="stylesheet">
+        <link href="css/font-awesome.css" rel="stylesheet"/>
         <link href="css/custome.css" rel="stylesheet">
         <link href="css/responsive.css" rel="stylesheet">
-        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.1/animate.css" integrity="sha512-K2J6Yt6ElUYEMPcTr0wm555AAyiqkgYiUgPIW18FT88/aYSNDk0EvGjsln/TEu3ee/jaHf0xoXzFppSbBtUXbQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
-        <link rel="preconnect" href="https://fonts.googleapis.com">
-<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-<link href="https://fonts.googleapis.com/css2?family=Raleway:wght@400;500;600;700&display=swap" rel="stylesheet">
+        <link href="css/animate.css" rel="stylesheet"/>
+        <link href="css/fonts.css" rel="stylesheet">
+        <!-- Matomo -->
+        <script>
+            var _paq = window._paq = window._paq || [];
+            /* We explicitly disable cookie tracking to avoid privacy issues */
+            _paq.push(['disableCookies']);
+            /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
+            _paq.push(['trackPageView']);
+            _paq.push(['enableLinkTracking']);
+            (function() {
+                var u="https://analytics.apache.org/";
+                _paq.push(['setTrackerUrl', u+'matomo.php']);
+                _paq.push(['setSiteId', '27']);
+                var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
+                g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
+            })();
+        </script>
+        <!-- End Matomo Code -->
     </head>
     <body>
-      <!-- header -->
-         <div class="header">
-            <div class="container">
-              <nav class="navbar navbar-expand-lg  ">
-                  <div class="container-fluid">
+    <!-- header -->
+    <div class="header">
+        <div class="container">
+            <nav class="navbar navbar-expand-lg  ">
+                <div class="container-fluid">
                     <a class="navbar-brand" href="index.html">
                         <img src="img/logo.png" class="img-fluid" alt="img">
                     </a>
-                    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
-                      <span class="fa fa-bars"></span>
+                    <button class="navbar-toggler" type="button" data-bs-toggle="collapse"
+                            data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
+                            aria-expanded="false" aria-label="Toggle navigation">
+                        <span class="fa fa-bars"></span>
                     </button>
                     <div class="collapse navbar-collapse" id="navbarSupportedContent">
-                      <ul class="navbar-nav ms-auto mb-2 mb-lg-0">
-                        <li class="nav-item">
-                          <a class="nav-link active" aria-current="page" href="index.html">Home</a>
-                        </li>
-                        <li class="nav-item">
-                          <a class="nav-link" href="download.html">Download</a>
-                        </li>
-                          <li class="nav-item dropdown">
-                              <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
-                                Documentation
-                              </a>
-                              <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
-                                 <li class="dropdown-header">Latest Documentation</li>
-                                 <li><a href="https://tinkerpop.apache.org/docs/current" class="dropdown-item">Documentation Index</a></li>
-                                 <li><a href="https://tinkerpop.apache.org/docs/current/reference" class="dropdown-item">Reference</a></li>
-                                 <li><a href="https://tinkerpop.apache.org/docs/current/dev/provider" class="dropdown-item">Provider</a></li>
-                                 <li><a href="https://tinkerpop.apache.org/docs/current/dev/developer" class="dropdown-item">Developer</a></li>
-                                 <li><a href="https://tinkerpop.apache.org/docs/current/upgrade" class="dropdown-item">Upgrade Information</a></li>
-                                 <li><a href="https://tinkerpop.apache.org/javadocs/current/core/" class="dropdown-item">Core Javadoc API</a></li>
-                                 <li><a href="https://tinkerpop.apache.org/javadocs/current/full/" class="dropdown-item">Full Javadoc API</a></li>
-                                 <li><hr class="dropdown-divider"></li>
-                                 <li><a href="https://tinkerpop.apache.org/docs/" class="dropdown-item">Documentation Archives</a></li>
-                                 <li><a href="https://tinkerpop.apache.org/javadocs/" class="dropdown-item">Javadoc Archives</a></li>
-                                 <li><hr class="dropdown-divider"></li>
-                                 <li><a href="https://tinkerpop.apache.org/docs/current/index.html#publications" class="dropdown-item">Publications</a></li>
-                              </ul>
-                              
+                        <ul class="navbar-nav ms-auto mb-2 mb-lg-0">
+                            <li class="nav-item">
+                                <a class="nav-link active" aria-current="page" href="index.html">Home</a>
                             </li>
-                         <li class="nav-item dropdown">
-                              <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown1" role="button" data-bs-toggle="dropdown" aria-expanded="false">
-                                Tutorials
-                              </a>
-                              <ul class="dropdown-menu" aria-labelledby="navbarDropdown1">
-                                     <li><a href="gremlin.html" class="dropdown-item">Introduction to Gremlin</a></li>
-                                     <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/tutorials/getting-started/" >Getting Started</a></li>
-                                     <li><a class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/tutorials/the-gremlin-console/">The Gremlin Console</a></li>
-                                     <li><a class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/recipes/">Gremlin Recipes</a></li>
-                                     <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/tutorials/gremlins-anatomy/">Gremlin's Anatomy</a></li>
-                                     <li><hr class="dropdown-divider"></li>
-                                     <li><a class="dropdown-item" href="http://kelvinlawrence.net/book/Gremlin-Graph-Guide.html">Book: Practical Gremlin by Kelvin Lawrence</a></li>
-                                     <li><a class="dropdown-item" href="http://sql2gremlin.com/">SQL2Gremlin</a></li>
-                                  </ul>
-                             
+                            <li class="nav-item">
+                                <a class="nav-link" href="download.html">Download</a>
                             </li>
-                         <li class="nav-item dropdown">
-                              <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown3" role="button" data-bs-toggle="dropdown" aria-expanded="false">
-                                Community
-                              </a>
-                              <ul class="dropdown-menu" aria-labelledby="navbarDropdown3">
-                                 <li><a class="dropdown-item" href="https://groups.google.com/group/gremlin-users">User Mailing List</a></li>
-                                 <li><a class="dropdown-item" href="https://lists.apache.org/list.html?dev@tinkerpop.apache.org">Developer Mailing List</a></li>
-                                 <li><a class="dropdown-item" href="https://discord.gg/ndMpKZcBEE" target="_blank"><img src="img/discord_logo.png" class="nav-icon">Join us on Discord</a></li>
-                                 <li><a class="dropdown-item" href="https://issues.apache.org/jira/browse/TINKERPOP/">Issue Tracker</a></li>
-                                 <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/dev/developer/#_contributing">Contributing</a></li>
-                                 <li><a class="dropdown-item" href="providers.html">Data System Support</a></li>
-                                 <li><a class="dropdown-item" href="community.html">Languages and Tools</a></li>
-                                 <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/dev/provider/#policies">Policies</a></li>
-                                <li><hr class="dropdown-divider"></li>
-                                 <li><a class="dropdown-item" href="https://github.com/apache/tinkerpop/"><img src="img/github-logo.png" class="nav-icon">GitHub</a></li>
-                                 <li><a class="dropdown-item" href="https://twitter.com/apachetinkerpop"><img src="img/twitter-logo.png" class="nav-icon">Twitter</a></li>
-                              </ul>
-                            
+
+                            <li class="nav-item dropdown">
+                                <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown4" role="button" data-bs-toggle="dropdown" aria-expanded="false">
+                                    Tools
+                                </a>
+                                <ul class="dropdown-menu" aria-labelledby="navbarDropdown4">
+                                    <li><a class="dropdown-item" href="providers.html">Graph Systems</a></li>
+                                    <li><a class="dropdown-item" href="community.html">Languages and Tools</a></li>
+                                    <li><hr class="dropdown-divider"></li>
+                                    <li><a class="dropdown-item" href="https://gremlify.com/">Gremlify: Try Gremlin</a></li>
+                                    <li><a class="dropdown-item" href="https://tinkerpop.apache.org/gremlint">Gremlint: Lint Gremlin</a></li>
+                                    <li><a class="dropdown-item" href="https://www.gremlator.com/">Gremlator: Translate Gremlin</a></li>
+                                </ul>
                             </li>
-                        
-                         <li class="nav-item">
-                          <a class="nav-link" href="https://tinkerpop.apache.org/gremlint/">Gremlint</a>
-                        </li>
-                        <li class="nav-item dropdown">
-                          <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown4" role="button" data-bs-toggle="dropdown" aria-expanded="false">
-                            Apache Software
-                          </a>
-                          <ul class="dropdown-menu" aria-labelledby="navbarDropdown4">
-                                 <li><a  class="dropdown-item" href="https://www.apache.org/">Apache Homepage</a></li>
-                                 <li><a class="dropdown-item" href="https://www.apache.org/licenses/">License</a></li>
-                                 <li><a class="dropdown-item" href="https://www.apache.org/events/current-event">Events</a></li>
-                                 <li><a class="dropdown-item" href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
-                                 <li><a class="dropdown-item" href="https://www.apache.org/foundation/thanks.html">Thanks</a></li>
-                                 <li><a class="dropdown-item" href="https://www.apache.org/security/">Security</a></li>
-                              </ul>
-                          
-                        </li>
-                         
-                      </ul>
+
+                            <li class="nav-item dropdown">
+                                <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
+                                   data-bs-toggle="dropdown" aria-expanded="false">
+                                    Documentation
+                                </a>
+                                <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
+                                    <li class="dropdown-header">Latest Documentation</li>
+                                    <li><a href="https://tinkerpop.apache.org/docs/current" class="dropdown-item">Documentation Index</a></li>
+                                    <li><a href="https://tinkerpop.apache.org/docs/current/reference" class="dropdown-item">Reference</a></li>
+                                    <li><a href="https://tinkerpop.apache.org/docs/current/dev/provider" class="dropdown-item">Provider</a></li>
+                                    <li><a href="https://tinkerpop.apache.org/docs/current/dev/developer" class="dropdown-item">Developer</a></li>
+                                    <li><a href="https://tinkerpop.apache.org/docs/current/upgrade" class="dropdown-item">Upgrade Information</a></li>
+                                    <li><a href="https://tinkerpop.apache.org/javadocs/current/core/" class="dropdown-item">Core Javadoc API</a></li>
+                                    <li><a href="https://tinkerpop.apache.org/javadocs/current/full/" class="dropdown-item">Full Javadoc API</a></li>
+                                    <li><hr class="dropdown-divider"></li>
+                                    <li><a href="https://tinkerpop.apache.org/docs/" class="dropdown-item">Documentation Archives</a></li>
+                                    <li><a href="https://tinkerpop.apache.org/javadocs/" class="dropdown-item">Javadoc Archives</a></li>
+                                    <li><hr class="dropdown-divider"></li>
+                                    <li><a href="https://tinkerpop.apache.org/docs/current/index.html#publications" class="dropdown-item">Publications</a></li>
+                                </ul>
+
+                            </li>
+
+                            <li class="nav-item dropdown">
+                                <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown1" role="button"
+                                   data-bs-toggle="dropdown" aria-expanded="false">
+                                    Tutorials
+                                </a>
+                                <ul class="dropdown-menu" aria-labelledby="navbarDropdown1">
+                                    <li><a href="gremlin.html" class="dropdown-item">Introduction to Gremlin</a></li>
+                                    <li><a class="dropdown-item"
+                                           href="https://tinkerpop.apache.org/docs/current/tutorials/getting-started/">Getting
+                                        Started</a></li>
+                                    <li><a class="dropdown-item"
+                                           href="https://tinkerpop.apache.org/docs/current/tutorials/the-gremlin-console/">The
+                                        Gremlin Console</a></li>
+                                    <li><a class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/recipes/">Gremlin
+                                        Recipes</a></li>
+                                    <li><a class="dropdown-item"
+                                           href="https://tinkerpop.apache.org/docs/current/tutorials/gremlins-anatomy/">Gremlin's
+                                        Anatomy</a></li>
+                                    <li>
+                                        <hr class="dropdown-divider">
+                                    </li>
+                                    <li><a class="dropdown-item"
+                                           href="http://kelvinlawrence.net/book/Gremlin-Graph-Guide.html">Book: Practical
+                                        Gremlin by Kelvin Lawrence</a></li>
+                                    <li><a class="dropdown-item" href="http://sql2gremlin.com/">SQL2Gremlin</a></li>
+                                </ul>
+
+                            </li>
+                            <li class="nav-item dropdown">
+                                <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown3" role="button" data-bs-toggle="dropdown" aria-expanded="false">
+                                    Community
+                                </a>
+                                <ul class="dropdown-menu" aria-labelledby="navbarDropdown3">
+                                    <li><a class="dropdown-item" href="https://discord.gg/kfebyvDM9H" target="_blank"><img src="img/discord-logo.png" class="nav-icon"/>Discord</a></li>
+                                    <li><a class="dropdown-item" href="https://www.answeroverflow.com/c/838910279550238720"><img src="img/answer-overflow-logo.png" class="nav-icon"/>Answer Overflow</a></li>
+                                    <li><a class="dropdown-item" href="https://stackoverflow.com/questions/tagged/gremlin"><img src="img/stack-overflow-logo.png" class="nav-icon"/>Stack Overflow</a></li>
+                                    <li><a class="dropdown-item" href="https://groups.google.com/group/gremlin-users"><img src="img/mail.png" class="nav-icon"/>User Mailing List</a></li>
+                                    <li><a class="dropdown-item" href="https://lists.apache.org/list.html?dev@tinkerpop.apache.org"><img src="img/mail.png" class="nav-icon"/>Developer Mailing List</a></li>
+                                    <li><a class="dropdown-item" href="https://issues.apache.org/jira/browse/TINKERPOP/"><img src="img/jira-logo.png" class="nav-icon"/>Issue Tracker</a></li>
+                                    <li><a class="dropdown-item" href="https://github.com/apache/tinkerpop/"><img src="img/github-logo.png" class="nav-icon"/>GitHub</a></li>
+                                    <li><a class="dropdown-item" href="https://www.twitch.tv/apachetinkerpop"><img src="img/twitch-logo.png" class="nav-icon"/>Twitch</a></li>
+                                    <li><a class="dropdown-item" href="https://twitter.com/apachetinkerpop"><img src="img/twitter-logo.png" class="nav-icon"/>Twitter</a></li>
+                                    <li><a class="dropdown-item" href="https://www.youtube.com/@apachetinkerpop"><img src="img/youtube-logo.png" class="nav-icon"/>YouTube</a></li>
+                                    <li><hr class="dropdown-divider"></li>
+                                    <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/dev/developer/#_contributing">Contributing</a></li>
+                                    <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/dev/provider/#policies">Policies</a></li>
+                                </ul>
+                            </li>
+                            <li class="nav-item dropdown">
+                                <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown5" role="button"
+                                   data-bs-toggle="dropdown" aria-expanded="false">
+                                    Apache Software
+                                </a>
+                                <ul class="dropdown-menu" aria-labelledby="navbarDropdown5">
+                                    <li><a class="dropdown-item" href="https://www.apache.org/">Apache Homepage</a></li>
+                                    <li><a class="dropdown-item" href="https://www.apache.org/licenses/">License</a></li>
+                                    <li><a class="dropdown-item"
+                                           href="https://www.apache.org/events/current-event">Events</a></li>
+                                    <li><a class="dropdown-item" href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a>
+                                    </li>
+                                    <li><a class="dropdown-item"
+                                           href="https://www.apache.org/foundation/thanks.html">Thanks</a></li>
+                                    <li><a class="dropdown-item" href="https://www.apache.org/security/">Security</a></li>
+                                </ul>
+
+                            </li>
+
+                        </ul>
                     </div>
-                  </div>
-                </nav>
-            </div>
+                </div>
+            </nav>
         </div>
+    </div>
         
         <!-- hero -->
         <div class="container hero-inner">
@@ -154,28 +202,28 @@
                 </div>
                 <div class="row d-flex align-items-center">
                     <div class="col-lg-3 col-md-6 mb-2 mb-lg-0">
-                        <img src="img/download/icon.png" class="img-fluid me-2" alt="img"> <span class="bold">3.6.0</span> (latest, stable) <p class="d-inline-block ms-4 mb-0">10-January-2022</p>
+                        <img src="img/download/icon.png" class="img-fluid me-2" alt="img"> <span class="bold">3.6.4</span> (latest, stable) <p class="d-inline-block ms-4 mb-0">12-May-2023</p>
                     </div>
                      <div class="col-lg-4 col-md-6 mb-2 mb-lg-0">
-                        <p class="text-blue mb-0"><a href="https://github.com/apache/tinkerpop/blob/3.6.0/CHANGELOG.asciidoc#release-3-6-0">release notes</a> | <a href="https://tinkerpop.apache.org/docs/3.6.0/upgrade/#_tinkerpop_3_6_0">upgrade</a> | <a href="https://tinkerpop.apache.org/docs/3.6.0/">documentation</a> | <a href="#" data-bs-toggle="modal" data-bs-target="#contributors-3_6_0">contributors</a></p>
+                        <p class="text-blue mb-0"><a href="https://github.com/apache/tinkerpop/blob/3.6.4/CHANGELOG.asciidoc#release-3-6-4">release notes</a> | <a href="https://tinkerpop.apache.org/docs/3.6.4/upgrade/#_tinkerpop_3_6_4">upgrade</a> | <a href="https://tinkerpop.apache.org/docs/3.6.4/">documentation</a> | <a href="#" data-bs-toggle="modal" data-bs-target="#contributors-3_6_4">contributors</a></p>
                      </div>
                       <div class="col-lg-5 col-md-12 mb-2 mb-lg-2">
-                        <a class="btn btn-theme me-2" href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.6.0/apache-tinkerpop-gremlin-console-3.6.0-bin.zip"><img src="img/download/bx-download.svg" class="img-fluid me-2" alt="img">Gremlin Console</a>
-                        <a class="btn btn-theme me-2" href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.6.0/apache-tinkerpop-gremlin-server-3.6.0-bin.zip"><img src="img/download/bx-download.svg" class="img-fluid me-2" alt="img">Gremlin Server</a>
-                        <a class="btn btn-theme me-2" href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.6.0/apache-tinkerpop-3.6.0-src.zip"><img src="img/download/bx-download.svg" class="img-fluid me-2" alt="img">Source</a>
+                        <a class="btn btn-theme me-2" href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.6.4/apache-tinkerpop-gremlin-console-3.6.4-bin.zip"><img src="img/download/bx-download.svg" class="img-fluid me-2" alt="img">Gremlin Console</a>
+                        <a class="btn btn-theme me-2" href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.6.4/apache-tinkerpop-gremlin-server-3.6.4-bin.zip"><img src="img/download/bx-download.svg" class="img-fluid me-2" alt="img">Gremlin Server</a>
+                        <a class="btn btn-theme me-2" href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.6.4/apache-tinkerpop-3.6.4-src.zip"><img src="img/download/bx-download.svg" class="img-fluid me-2" alt="img">Source</a>
                       </div>
                 </div>
                 <div class="row d-flex align-items-center">
                     <div class="col-lg-3 col-md-6 mb-2 mb-lg-0">
-                        <img src="img/download/icon.png" class="img-fluid me-2" alt="img"> <span class="bold">3.5.3</span> (maintenance) <p class="d-inline-block ms-4 mb-0">10-January-2022</p>
+                        <img src="img/download/icon.png" class="img-fluid me-2" alt="img"> <span class="bold">3.5.6</span> (maintenance) <p class="d-inline-block ms-4 mb-0">1-May-2023</p>
                     </div>
                      <div class="col-lg-4 col-md-6 mb-2 mb-lg-0">
-                        <p class="text-blue mb-0"><a href="https://github.com/apache/tinkerpop/blob/3.5.3/CHANGELOG.asciidoc#release-3-5-3">release notes</a> | <a href="https://tinkerpop.apache.org/docs/3.5.3/upgrade/#_tinkerpop_3_5_3">upgrade</a> | <a href="https://tinkerpop.apache.org/docs/3.5.3/">documentation</a> | <a href="#" data-bs-toggle="modal" data-bs-target="#contributors-3_5_3">contributors</a></p>
+                        <p class="text-blue mb-0"><a href="https://github.com/apache/tinkerpop/blob/3.5.6/CHANGELOG.asciidoc#release-3-5-6">release notes</a> | <a href="https://tinkerpop.apache.org/docs/3.5.6/upgrade/#_tinkerpop_3_5_6">upgrade</a> | <a href="https://tinkerpop.apache.org/docs/3.5.6/">documentation</a> | <a href="#" data-bs-toggle="modal" data-bs-target="#contributors-3_5_6">contributors</a></p>
                      </div>
                       <div class="col-lg-5 col-md-12 mb-2 mb-lg-0">
-                        <a class="btn btn-theme me-2" href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.5.3/apache-tinkerpop-gremlin-console-3.5.3-bin.zip"><img src="img/download/bx-download.svg" class="img-fluid me-2" alt="img">Gremlin Console</a>
-                        <a class="btn btn-theme me-2" href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.5.3/apache-tinkerpop-gremlin-server-3.5.3-bin.zip"><img src="img/download/bx-download.svg" class="img-fluid me-2" alt="img">Gremlin Server</a>
-                        <a class="btn btn-theme me-2" href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.5.3/apache-tinkerpop-3.5.3-src.zip"><img src="img/download/bx-download.svg" class="img-fluid me-2" alt="img">Source</a>
+                        <a class="btn btn-theme me-2" href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.5.6/apache-tinkerpop-gremlin-console-3.5.6-bin.zip"><img src="img/download/bx-download.svg" class="img-fluid me-2" alt="img">Gremlin Console</a>
+                        <a class="btn btn-theme me-2" href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.5.6/apache-tinkerpop-gremlin-server-3.5.6-bin.zip"><img src="img/download/bx-download.svg" class="img-fluid me-2" alt="img">Gremlin Server</a>
+                        <a class="btn btn-theme me-2" href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.5.6/apache-tinkerpop-3.5.6-src.zip"><img src="img/download/bx-download.svg" class="img-fluid me-2" alt="img">Source</a>
                       </div>
                 </div>
 
@@ -184,7 +232,14 @@
                     <div class="col-lg-3 col-md-6 mb-2 mb-lg-0">
                         <img src="img/download/icon.png" class="img-fluid me-2" alt="img">
                         <select  id="dropdownArchives" class="form-select d-inliine-block">
-                             <option selected="selected">3.5.2 (10-January-2022)</option>
+                             <option selected="selected">3.6.3 (1-May-2023)</option>
+                                <option>3.6.2 (16-January-2023)</option>
+                                <option>3.6.1 (18-July-2922)</option>
+                                <option>3.6.0 (4-April-2022)</option>
+                                <option>3.5.5 (16-January-2023)</option>
+                                <option>3.5.4 (18-July-2022)</option>
+                                <option>3.5.3 (4-April-2022)</option>
+                                <option>3.5.2 (10-January-2022)</option>
                                 <option>3.5.1 (19-July-2021)</option>
                                 <option>3.5.0 (3-May-2021)</option>
                                 <option>3.4.13 (10-January-2022)</option>
@@ -307,10 +362,10 @@
 
                             <tr>
                                 <td data-label="Repository" class="bold">Go Module</td>
-                                <td data-label="Artifacts">COMING SOON</td>
+                                <td data-label="Artifacts"><a href="https://pkg.go.dev/github.com/apache/tinkerpop/gremlin-go/v3" class="text-blue">gremlin-go</a></td>
                                 <td data-label="">
                                     <div class="code-box1">
-                                        COMING SOON
+                                        go get github.com/apache/tinkerpop/gremlin-go/v3&#64;v3.6.4
                                     </div>
                                 </td>
                             </tr>
@@ -324,7 +379,7 @@
                                         &lt;dependency> <br>
                                            &nbsp;&nbsp; &lt;groupId>org.apache.tinkerpop&lt;/groupId> <br>
                                            &nbsp;&nbsp; &lt;artifactId>gremlin-driver&lt;/artifactId> <br>
-                                          &nbsp;&nbsp;  &lt;version>3.5.1&lt;/version> <br>
+                                          &nbsp;&nbsp;  &lt;version>3.6.4&lt;/version> <br>
                                         &lt;/dependency>
                                   </div>
                               </td>
@@ -355,7 +410,7 @@
                               <td data-label="Artifacts"><a href="https://www.nuget.org/packages/Gremlin.Net/" class="text-blue">Gremlin.Net </a> <br> <a href="https://www.nuget.org/packages/Gremlin.Net.Template/" class="text-blue">Gremlin.Net.Template </a></td>
                               <td data-label="">
                                   <div class="code-box1">
-                                   dotnet add package Gremlin.Net --version 3.5.1 <br>dotnet add package Gremlin.Net.template --version 3.5.1
+                                   dotnet add package Gremlin.Net --version 3.6.4 <br>dotnet add package Gremlin.Net.template --version 3.6.4
                                   </div>
                               </td>
                             </tr>
@@ -412,6 +467,150 @@
 
    
     <!-- Contributor Modals -->
+    <!-- 3.6.4 -->
+    <div class="modal fade" id="contributors-3_6_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-bs-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+
+                </div>
+                <div class="modal-body">
+                    <h4 class="modal-title bold black mb-2 ">3.6.4</h4>
+                    <p>Release Manager: Yang Xia</p>
+
+                    <div class="code-box1"><pre><code>$ git shortlog -sn 3.6.3..3.6.4
+     9  Yang Xia
+     5  xiazcy
+     2  Florian Hockmann
+     1  Cole Greer
+     1  Valentyn Kahamlyk</code></pre></div>
+                </div>
+
+            </div>
+        </div>
+    </div>
+
+    <!-- 3.6.3 -->
+    <div class="modal fade" id="contributors-3_6_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-bs-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+
+                </div>
+                <div class="modal-body">
+                    <h4 class="modal-title bold black mb-2 ">3.6.3</h4>
+                    <p>Release Manager: Yang Xia</p>
+
+                    <div class="code-box1"><pre><code>$ git shortlog -sn 3.6.2..3.6.3
+    51  Stephen Mallette
+    48  Yang Xia
+    25  Ken Hu
+    13  Valentyn Kahamlyk
+    13  Cole Greer
+    13  dependabot[bot]
+    11  kenhuuu
+    10  valentynk
+     7  Florian Hockmann
+     4  Oleksandr Porunov
+     3  xiazcy
+     2  Hongjiang Zhang
+     2  Kemal
+     2  iAmmarTahir
+     1  Phanindhra
+     1  Daniel Weber
+     1  Derposoft
+     1  Mike Personick
+     1  Aaron Coady
+     1  Tormod Haugene
+     1  lvca</code></pre></div>
+                </div>
+
+            </div>
+        </div>
+    </div>
+
+      <!-- 3.6.2 -->
+      <div class="modal fade" id="contributors-3_6_2" tabindex="-1" role="dialog">
+          <div class="modal-dialog" role="document">
+              <div class="modal-content">
+                  <div class="modal-header">
+                      <button type="button" class="close" data-bs-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+
+                  </div>
+                  <div class="modal-body">
+                      <h4 class="modal-title bold black mb-2 ">3.6.2</h4>
+                      <p>Release Manager: Yang Xia</p>
+
+                      <div class="code-box1"><pre><code>$ git shortlog -sn 3.6.1..3.6.2
+   153  Stephen Mallette
+    59  Florian Hockmann
+    46  Yang Xia
+    38  dependabot[bot]
+    35  Valentyn Kahamlyk
+    12  Cole Greer
+    10  Ken Hu
+     4  Aaron Coady
+     3  Hongjiang Zhang
+     3  Rithin Kumar
+     3  tkolanko
+     2  Mike Personick
+     2  good41898
+     1  宁培培
+     1  Boxuan Li
+     1  Norio Akagi (norakagi)
+     1  OGoodness
+     1  Priyanka Awatramani
+     1  Willem Broekema</code></pre></div>
+                  </div>
+
+              </div>
+          </div>
+      </div>
+
+      <!-- 3.6.1 -->
+      <div class="modal fade" id="contributors-3_6_1" tabindex="-1" role="dialog">
+          <div class="modal-dialog" role="document">
+              <div class="modal-content">
+                  <div class="modal-header">
+                      <button type="button" class="close" data-bs-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+
+                  </div>
+                  <div class="modal-body">
+                      <h4 class="modal-title bold black mb-2 ">3.6.1</h4>
+                      <p>Release Manager: Kelvin Lawrence</p>
+
+                      <div class="code-box1"><pre><code>$ git shortlog -sn 3.6.0..3.6.1
+   122  Stephen Mallette
+    81  Igor Ostapenko
+    56  Lyndon Bauto
+    49  Valentyn Kahamlyk
+    23  Rithin Kumar
+    19  Florian Hockmann
+    18  Simon Zhao
+    18  Yang Xia
+    15  Roi Martin
+    14  Dave Bechberger
+    12  dependabot[bot]
+     4  Daniel Weber
+     4  Jorge Bay-Gondra
+     4  Mike Personick
+     2  Dan DeRobertis
+     2  Ken Hu
+     2  Norio Akagi (norakagi)
+     1  Boxuan Li
+     1  Saikiran Boga
+     1  Vivek Gupta
+     1  c
+     1  felix
+     1  steigma</code></pre></div>
+                  </div>
+
+              </div>
+          </div>
+      </div>
+
       <!-- 3.6.0 -->
       <div class="modal fade" id="contributors-3_6_0" tabindex="-1" role="dialog">
           <div class="modal-dialog" role="document">
@@ -459,6 +658,119 @@
           </div>
       </div>
 
+    <!-- 3.5.6 -->
+    <div class="modal fade" id="contributors-3_5_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-bs-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+
+                </div>
+                <div class="modal-body">
+                    <h4 class="modal-title bold black mb-2 ">3.5.6</h4>
+                    <p>Release Manager: Yang Xia</p>
+
+                    <div class="code-box1"><pre><code>$ git shortlog -sn 3.5.5..3.5.6
+    21  Stephen Mallette
+    14  Yang Xia
+    13  dependabot[bot]
+    10  Valentyn Kahamlyk
+     9  kenhuuu
+     9  Cole Greer
+     7  Ken Hu
+     4  Florian Hockmann
+     3  valentynk
+     2  xiazcy
+     2  Hongjiang Zhang
+     2  Kemal
+     2  iAmmarTahir
+     1  Aaron Coady
+     1  Derposoft
+     1  Daniel Weber
+     1  Tormod Haugene</code></pre></div>
+                </div>
+
+            </div>
+        </div>
+    </div>
+
+      <!-- 3.5.5 -->
+      <div class="modal fade" id="contributors-3_5_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-bs-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+
+                  </div>
+                  <div class="modal-body">
+                      <h4 class="modal-title bold black mb-2 ">3.5.5</h4>
+                      <p>Release Manager: Yang Xia</p>
+
+                      <div class="code-box1"><pre><code>$  git shortlog -sn 3.5.4..3.5.5
+    67  Stephen Mallette
+    37  dependabot[bot]
+    32  Florian Hockmann
+    23  Yang Xia
+    21  Valentyn Kahamlyk
+    10  Cole Greer
+     7  Ken Hu
+     4  Aaron Coady
+     3  Hongjiang Zhang
+     3  Rithin Kumar
+     2  good41898
+     1  Priyanka Awatramani
+     1  Willem Broekema
+     1  OGoodness
+     1  Norio Akagi (norakagi)
+     1  Boxuan Li</code></pre></div>
+                  </div>
+
+              </div>
+          </div>
+      </div>
+
+      <!-- 3.5.4 -->
+      <div class="modal fade" id="contributors-3_5_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-bs-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+
+                  </div>
+                  <div class="modal-body">
+                      <h4 class="modal-title bold black mb-2 ">3.5.4</h4>
+                      <p>Release Manager: Kelvin Lawrence</p>
+
+                      <div class="code-box1"><pre><code>$  git shortlog -sn 3.5.3..3.5.4
+    81  Igor Ostapenko
+    52  Stephen Mallette
+    43  Valentyn Kahamlyk
+    23  Lyndon Bauto
+    21  Rithin Kumar
+    18  Yang Xia
+    16  Simon Zhao
+    14  Roi Martin
+    13  Florian Hockmann
+    12  dependabot[bot]
+     6  Dave Bechberger
+     2  Daniel Weber
+     2  Jorge Bay-Gondra
+     2  Ken Hu
+     2  Mike Personick
+     1  Boxuan Li
+     1  Dan DeRobertis
+     1  Norio Akagi (norakagi)
+     1  Saikiran Boga
+     1  Vivek Gupta
+     1  c
+     1  felix
+     1  steigma</code></pre></div>
+                  </div>
+
+              </div>
+          </div>
+      </div>
+
       <!-- 3.5.3 -->
       <div class="modal fade" id="contributors-3_5_3" tabindex="-1" role="dialog">
           <div class="modal-dialog" role="document">
@@ -2092,9 +2404,9 @@
                 <div class="row d-flex justify-content-center">
                     <div class="col-md-8 col-lg-6">
                         <div class="ju-box">
-                            <h2 class="ft-40 text-blue bold">Join Us on</h2>
-                            <p class="bold">Join us on our Discord Chat</p>
-                            <a href="https://discord.gg/ndMpKZcBEE"><img src="img/tpvewx.png" class="img-fluid mt-3" alt="img"></a>
+                            <h2 class="ft-40 text-blue bold">Join Us</h2>
+                            <p class="bold">Join us on our Discord Server</p>
+                            <a href="https://discord.gg/kfebyvDM9H"><img src="img/tpvewx.png" class="img-fluid mt-3" alt="img"></a>
                         </div>
                     </div>
                 </div>
@@ -2111,9 +2423,11 @@
                             <div class="bold ft-25">Apache TinkerPop™</div>
                             <p class="mt-2 mb-4">Apache TinkerPop™ is a graph computing framework for both graph databases (OLTP) and graph analytic systems (OLAP).</p>
                             <ul class="list-unstyled list-inline hover-op-low">
-                                <li class="list-inline-item"><a href="https://discord.gg/ndMpKZcBEE"><img src="img/social/discord.svg" class="img-fluid" alt="img"></a></li>
-                                <li class="list-inline-item"><a href="https://twitter.com/apachetinkerpop"><img src="img/social/twitter-square.svg" class="img-fluid" alt="img"></a></li>
+                                <li class="list-inline-item"><a href="https://discord.gg/kfebyvDM9H"><img src="img/social/discord.svg" class="img-fluid" alt="img"></a></li>
                                 <li class="list-inline-item"><a href="https://github.com/apache/tinkerpop"><img src="img/social/github-box.svg" class="img-fluid" alt="img"></a></li>
+                                <li class="list-inline-item"><a href="https://www.twitch.tv/apachetinkerpop"><img src="img/social/twitch.png" class="img-fluid" alt="img"></a></li>
+                                <li class="list-inline-item"><a href="https://twitter.com/apachetinkerpop"><img src="img/social/twitter-square.svg" class="img-fluid" alt="img"></a></li>
+                                <li class="list-inline-item"><a href="https://www.youtube.com/@apachetinkerpop"><img src="img/social/youtube.png" class="img-fluid" alt="img"></a></li>
                             </ul>
                         </div>
                         <div class="col-md-4 ft-links">
@@ -2124,6 +2438,7 @@
                                         <li><a href="index.html">Home</a></li>
                                         <li><a href="download.html">Downloads</a></li>
                                         <li><a href="https://tinkerpop.apache.org/docs/current">Documentation</a></li>
+                                        <li><a href="https://privacy.apache.org/policies/privacy-policy-public.html" target="_blank">Privacy Policy</a></li>
                                     </ul>
                                 </div>
                                 <div class="col-lg-6">
@@ -2145,7 +2460,7 @@
                 <div class="container">
                     <div class="row">
                         <div class="col-12">
-                            Copyright © 2015-2022 The Apache Software Foundation
+                            Copyright © 2015-2023 The Apache Software Foundation
                         </div>
                     </div>
                 </div>
@@ -2153,9 +2468,7 @@
         </footer>
         <script src="js/jquery-1.11.1.js"></script>
         <script src="js/bootstrap.bundle.min.js"></script>
-      <script src="https://cdnjs.cloudflare.com/ajax/libs/wow/1.1.2/wow.min.js"
-              integrity="sha512-Eak/29OTpb36LLo2r47IpVzPBLXnAMPAVypbSZiZ4Qkf8p/7S/XRG5xp7OKWPPYfJT6metI+IORkR5G8F900+g=="
-              crossorigin="anonymous" referrerpolicy="no-referrer"></script>
+      <script src="js/wow.min.js"></script>
         <script src="js/my.js"></script>
     </body>
 </html>
diff --git a/docs/site/home/fonts/raleway.woff2 b/docs/site/home/fonts/raleway.woff2
new file mode 100644
index 0000000..33cb165
--- /dev/null
+++ b/docs/site/home/fonts/raleway.woff2
Binary files differ
diff --git a/docs/site/home/gremlin.html b/docs/site/home/gremlin.html
index 901610f..485ea8e 100644
--- a/docs/site/home/gremlin.html
+++ b/docs/site/home/gremlin.html
@@ -19,119 +19,167 @@
         <meta http-equiv="X-UA-Compatible" content="IE=edge">
         <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
         <link href="img/favicon.png" rel="shortcut icon" />
-        <title>Apache TinkerPop</title>
+        <title>Apache TinkerPop: Gremlin</title>
         <meta name="description" content="">
         <meta name="keywords" content="">
-        <link href="css/bootstrap.min.css" rel="stylesheet"><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" integrity="sha512-5A8nwdMOWrSz20fDsjczgUidUBR8liPYU+WymTZP1lmY9G6Oc7HlZv156XqnsgNUzTyMefFTcsFH/tnJE/+xBg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
+        <link href="css/bootstrap.min.css" rel="stylesheet">
+        <link href="css/font-awesome.css" rel="stylesheet"/>
         <link href="css/custome.css" rel="stylesheet">
         <link href="css/responsive.css" rel="stylesheet">
-        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.1/animate.css" integrity="sha512-K2J6Yt6ElUYEMPcTr0wm555AAyiqkgYiUgPIW18FT88/aYSNDk0EvGjsln/TEu3ee/jaHf0xoXzFppSbBtUXbQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
+        <link href="css/animate.css" rel="stylesheet"/>
         <link href="css/prism.css" rel="stylesheet">
-        <link rel="preconnect" href="https://fonts.googleapis.com">
-<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-<link href="https://fonts.googleapis.com/css2?family=Raleway:wght@400;500;600;700&display=swap" rel="stylesheet">
+        <link href="css/fonts.css" rel="stylesheet">
+        <!-- Matomo -->
+        <script>
+            var _paq = window._paq = window._paq || [];
+            /* We explicitly disable cookie tracking to avoid privacy issues */
+            _paq.push(['disableCookies']);
+            /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
+            _paq.push(['trackPageView']);
+            _paq.push(['enableLinkTracking']);
+            (function() {
+                var u="https://analytics.apache.org/";
+                _paq.push(['setTrackerUrl', u+'matomo.php']);
+                _paq.push(['setSiteId', '27']);
+                var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
+                g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
+            })();
+        </script>
+        <!-- End Matomo Code -->
     </head>
     <body>
-      <!-- header -->
-         <div class="header">
-            <div class="container">
-              <nav class="navbar navbar-expand-lg  ">
-                  <div class="container-fluid">
+    <!-- header -->
+    <div class="header">
+        <div class="container">
+            <nav class="navbar navbar-expand-lg  ">
+                <div class="container-fluid">
                     <a class="navbar-brand" href="index.html">
                         <img src="img/logo.png" class="img-fluid" alt="img">
                     </a>
-                    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
-                      <span class="fa fa-bars"></span>
+                    <button class="navbar-toggler" type="button" data-bs-toggle="collapse"
+                            data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
+                            aria-expanded="false" aria-label="Toggle navigation">
+                        <span class="fa fa-bars"></span>
                     </button>
                     <div class="collapse navbar-collapse" id="navbarSupportedContent">
-                      <ul class="navbar-nav ms-auto mb-2 mb-lg-0">
-                        <li class="nav-item">
-                          <a class="nav-link active" aria-current="page" href="index.html">Home</a>
-                        </li>
-                        <li class="nav-item">
-                          <a class="nav-link" href="download.html">Download</a>
-                        </li>
-                          <li class="nav-item dropdown">
-                              <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
-                                Documentation
-                              </a>
-                              <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
-                                  <li class="dropdown-header">Latest Documentation</li>
-                                  <li><a href="https://tinkerpop.apache.org/docs/current" class="dropdown-item">Documentation Index</a></li>
-                                  <li><a href="https://tinkerpop.apache.org/docs/current/reference" class="dropdown-item">Reference</a></li>
-                                  <li><a href="https://tinkerpop.apache.org/docs/current/dev/provider" class="dropdown-item">Provider</a></li>
-                                  <li><a href="https://tinkerpop.apache.org/docs/current/dev/developer" class="dropdown-item">Developer</a></li>
-                                  <li><a href="https://tinkerpop.apache.org/docs/current/upgrade" class="dropdown-item">Upgrade Information</a></li>
-                                  <li><a href="https://tinkerpop.apache.org/javadocs/current/core/" class="dropdown-item">Core Javadoc API</a></li>
-                                  <li><a href="https://tinkerpop.apache.org/javadocs/current/full/" class="dropdown-item">Full Javadoc API</a></li>
-                                  <li><hr class="dropdown-divider"></li>
-                                  <li><a href="https://tinkerpop.apache.org/docs/" class="dropdown-item">Documentation Archives</a></li>
-                                  <li><a href="https://tinkerpop.apache.org/javadocs/" class="dropdown-item">Javadoc Archives</a></li>
-                                  <li><hr class="dropdown-divider"></li>
-                                  <li><a href="https://tinkerpop.apache.org/docs/current/index.html#publications" class="dropdown-item">Publications</a></li>
-                              </ul>
-                              
+                        <ul class="navbar-nav ms-auto mb-2 mb-lg-0">
+                            <li class="nav-item">
+                                <a class="nav-link active" aria-current="page" href="index.html">Home</a>
                             </li>
-                         <li class="nav-item dropdown">
-                              <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown1" role="button" data-bs-toggle="dropdown" aria-expanded="false">
-                                Tutorials
-                              </a>
-                              <ul class="dropdown-menu" aria-labelledby="navbarDropdown1">
-                                     <li><a href="gremlin.html" class="dropdown-item">Introduction to Gremlin</a></li>
-                                     <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/tutorials/getting-started/" >Getting Started</a></li>
-                                     <li><a class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/tutorials/the-gremlin-console/">The Gremlin Console</a></li>
-                                     <li><a class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/recipes/">Gremlin Recipes</a></li>
-                                     <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/tutorials/gremlins-anatomy/">Gremlin's Anatomy</a></li>
-                                     <li><hr class="dropdown-divider"></li>
-                                     <li><a class="dropdown-item" href="http://kelvinlawrence.net/book/Gremlin-Graph-Guide.html">Book: Practical Gremlin by Kelvin Lawrence</a></li>
-                                     <li><a class="dropdown-item" href="http://sql2gremlin.com/">SQL2Gremlin</a></li>
-                                  </ul>
-                             
+                            <li class="nav-item">
+                                <a class="nav-link" href="download.html">Download</a>
                             </li>
-                         <li class="nav-item dropdown">
-                              <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown3" role="button" data-bs-toggle="dropdown" aria-expanded="false">
-                                Community
-                              </a>
-                              <ul class="dropdown-menu" aria-labelledby="navbarDropdown3">
-                                 <li><a class="dropdown-item" href="https://groups.google.com/group/gremlin-users">User Mailing List</a></li>
-                                 <li><a class="dropdown-item" href="https://lists.apache.org/list.html?dev@tinkerpop.apache.org">Developer Mailing List</a></li>
-                                 <li><a class="dropdown-item" href="https://discord.gg/ndMpKZcBEE" target="_blank"><img src="img/discord_logo.png" class="nav-icon">Join us on Discord</a></li>
-                                 <li><a class="dropdown-item" href="https://issues.apache.org/jira/browse/TINKERPOP/">Issue Tracker</a></li>
-                                 <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/dev/developer/#_contributing">Contributing</a></li>
-                                 <li><a class="dropdown-item" href="providers.html">Data System Support</a></li>
-                                 <li><a class="dropdown-item" href="community.html">Languages and Tools</a></li>
-                                 <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/dev/provider/#policies">Policies</a></li>
-                                <li><hr class="dropdown-divider"></li>
-                                 <li><a class="dropdown-item" href="https://github.com/apache/tinkerpop/"><img src="img/github-logo.png" class="nav-icon">GitHub</a></li>
-                                 <li><a class="dropdown-item" href="https://twitter.com/apachetinkerpop"><img src="img/twitter-logo.png" class="nav-icon">Twitter</a></li>
-                              </ul>
-                            
+
+                            <li class="nav-item dropdown">
+                                <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown4" role="button" data-bs-toggle="dropdown" aria-expanded="false">
+                                    Tools
+                                </a>
+                                <ul class="dropdown-menu" aria-labelledby="navbarDropdown4">
+                                    <li><a class="dropdown-item" href="providers.html">Graph Systems</a></li>
+                                    <li><a class="dropdown-item" href="community.html">Languages and Tools</a></li>
+                                    <li><hr class="dropdown-divider"></li>
+                                    <li><a class="dropdown-item" href="https://gremlify.com/">Gremlify: Try Gremlin</a></li>
+                                    <li><a class="dropdown-item" href="https://tinkerpop.apache.org/gremlint">Gremlint: Lint Gremlin</a></li>
+                                    <li><a class="dropdown-item" href="https://www.gremlator.com/">Gremlator: Translate Gremlin</a></li>
+                                </ul>
                             </li>
-                        
-                         <li class="nav-item">
-                          <a class="nav-link" href="https://tinkerpop.apache.org/gremlint/">Gremlint</a>
-                        </li>
-                        <li class="nav-item dropdown">
-                          <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown4" role="button" data-bs-toggle="dropdown" aria-expanded="false">
-                            Apache Software
-                          </a>
-                          <ul class="dropdown-menu" aria-labelledby="navbarDropdown4">
-                                 <li><a  class="dropdown-item" href="https://www.apache.org/">Apache Homepage</a></li>
-                                 <li><a class="dropdown-item" href="https://www.apache.org/licenses/">License</a></li>
-                                 <li><a class="dropdown-item" href="https://www.apache.org/events/current-event">Events</a></li>
-                                 <li><a class="dropdown-item" href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
-                                 <li><a class="dropdown-item" href="https://www.apache.org/foundation/thanks.html">Thanks</a></li>
-                                 <li><a class="dropdown-item" href="https://www.apache.org/security/">Security</a></li>
-                              </ul>
-                          
-                        </li>
-                         
-                      </ul>
+
+                            <li class="nav-item dropdown">
+                                <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
+                                   data-bs-toggle="dropdown" aria-expanded="false">
+                                    Documentation
+                                </a>
+                                <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
+                                    <li class="dropdown-header">Latest Documentation</li>
+                                    <li><a href="https://tinkerpop.apache.org/docs/current" class="dropdown-item">Documentation Index</a></li>
+                                    <li><a href="https://tinkerpop.apache.org/docs/current/reference" class="dropdown-item">Reference</a></li>
+                                    <li><a href="https://tinkerpop.apache.org/docs/current/dev/provider" class="dropdown-item">Provider</a></li>
+                                    <li><a href="https://tinkerpop.apache.org/docs/current/dev/developer" class="dropdown-item">Developer</a></li>
+                                    <li><a href="https://tinkerpop.apache.org/docs/current/upgrade" class="dropdown-item">Upgrade Information</a></li>
+                                    <li><a href="https://tinkerpop.apache.org/javadocs/current/core/" class="dropdown-item">Core Javadoc API</a></li>
+                                    <li><a href="https://tinkerpop.apache.org/javadocs/current/full/" class="dropdown-item">Full Javadoc API</a></li>
+                                    <li><hr class="dropdown-divider"></li>
+                                    <li><a href="https://tinkerpop.apache.org/docs/" class="dropdown-item">Documentation Archives</a></li>
+                                    <li><a href="https://tinkerpop.apache.org/javadocs/" class="dropdown-item">Javadoc Archives</a></li>
+                                    <li><hr class="dropdown-divider"></li>
+                                    <li><a href="https://tinkerpop.apache.org/docs/current/index.html#publications" class="dropdown-item">Publications</a></li>
+                                </ul>
+
+                            </li>
+
+                            <li class="nav-item dropdown">
+                                <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown1" role="button"
+                                   data-bs-toggle="dropdown" aria-expanded="false">
+                                    Tutorials
+                                </a>
+                                <ul class="dropdown-menu" aria-labelledby="navbarDropdown1">
+                                    <li><a href="gremlin.html" class="dropdown-item">Introduction to Gremlin</a></li>
+                                    <li><a class="dropdown-item"
+                                           href="https://tinkerpop.apache.org/docs/current/tutorials/getting-started/">Getting
+                                        Started</a></li>
+                                    <li><a class="dropdown-item"
+                                           href="https://tinkerpop.apache.org/docs/current/tutorials/the-gremlin-console/">The
+                                        Gremlin Console</a></li>
+                                    <li><a class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/recipes/">Gremlin
+                                        Recipes</a></li>
+                                    <li><a class="dropdown-item"
+                                           href="https://tinkerpop.apache.org/docs/current/tutorials/gremlins-anatomy/">Gremlin's
+                                        Anatomy</a></li>
+                                    <li>
+                                        <hr class="dropdown-divider">
+                                    </li>
+                                    <li><a class="dropdown-item"
+                                           href="http://kelvinlawrence.net/book/Gremlin-Graph-Guide.html">Book: Practical
+                                        Gremlin by Kelvin Lawrence</a></li>
+                                    <li><a class="dropdown-item" href="http://sql2gremlin.com/">SQL2Gremlin</a></li>
+                                </ul>
+
+                            </li>
+                            <li class="nav-item dropdown">
+                                <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown3" role="button" data-bs-toggle="dropdown" aria-expanded="false">
+                                    Community
+                                </a>
+                                <ul class="dropdown-menu" aria-labelledby="navbarDropdown3">
+                                    <li><a class="dropdown-item" href="https://discord.gg/kfebyvDM9H" target="_blank"><img src="img/discord-logo.png" class="nav-icon"/>Discord</a></li>
+                                    <li><a class="dropdown-item" href="https://www.answeroverflow.com/c/838910279550238720"><img src="img/answer-overflow-logo.png" class="nav-icon"/>Answer Overflow</a></li>
+                                    <li><a class="dropdown-item" href="https://stackoverflow.com/questions/tagged/gremlin"><img src="img/stack-overflow-logo.png" class="nav-icon"/>Stack Overflow</a></li>
+                                    <li><a class="dropdown-item" href="https://groups.google.com/group/gremlin-users"><img src="img/mail.png" class="nav-icon"/>User Mailing List</a></li>
+                                    <li><a class="dropdown-item" href="https://lists.apache.org/list.html?dev@tinkerpop.apache.org"><img src="img/mail.png" class="nav-icon"/>Developer Mailing List</a></li>
+                                    <li><a class="dropdown-item" href="https://issues.apache.org/jira/browse/TINKERPOP/"><img src="img/jira-logo.png" class="nav-icon"/>Issue Tracker</a></li>
+                                    <li><a class="dropdown-item" href="https://github.com/apache/tinkerpop/"><img src="img/github-logo.png" class="nav-icon"/>GitHub</a></li>
+                                    <li><a class="dropdown-item" href="https://www.twitch.tv/apachetinkerpop"><img src="img/twitch-logo.png" class="nav-icon"/>Twitch</a></li>
+                                    <li><a class="dropdown-item" href="https://twitter.com/apachetinkerpop"><img src="img/twitter-logo.png" class="nav-icon"/>Twitter</a></li>
+                                    <li><a class="dropdown-item" href="https://www.youtube.com/@apachetinkerpop"><img src="img/youtube-logo.png" class="nav-icon"/>YouTube</a></li>
+                                    <li><hr class="dropdown-divider"></li>
+                                    <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/dev/developer/#_contributing">Contributing</a></li>
+                                    <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/dev/provider/#policies">Policies</a></li>
+                                </ul>
+                            </li>
+                            <li class="nav-item dropdown">
+                                <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown5" role="button"
+                                   data-bs-toggle="dropdown" aria-expanded="false">
+                                    Apache Software
+                                </a>
+                                <ul class="dropdown-menu" aria-labelledby="navbarDropdown5">
+                                    <li><a class="dropdown-item" href="https://www.apache.org/">Apache Homepage</a></li>
+                                    <li><a class="dropdown-item" href="https://www.apache.org/licenses/">License</a></li>
+                                    <li><a class="dropdown-item"
+                                           href="https://www.apache.org/events/current-event">Events</a></li>
+                                    <li><a class="dropdown-item" href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a>
+                                    </li>
+                                    <li><a class="dropdown-item"
+                                           href="https://www.apache.org/foundation/thanks.html">Thanks</a></li>
+                                    <li><a class="dropdown-item" href="https://www.apache.org/security/">Security</a></li>
+                                </ul>
+
+                            </li>
+
+                        </ul>
                     </div>
-                  </div>
-                </nav>
-            </div>
+                </div>
+            </nav>
         </div>
+    </div>
         
         <!-- hero -->
         <div class="container hero-inner">
@@ -325,7 +373,7 @@
                     <div class="col-md-12 col-lg-6 mb-4 mb-lg-0">
                         <div class="code-box h-100">
                                                     <code>
-                                                        <span class="text-purpal">g</span><span class="text-blue">.V</span><span class="text-success">().</span><span class="text-blue">has</span><span class="text-success">("name","gremlin").</span> <span class="text-blue">as</span><span class="text-success">("a").</span>
+                                                        <span class="text-purpal">g</span><span class="text-blue">.V</span><span class="text-success">().</span><span class="text-blue">has</span><span class="text-success">("name","gremlin").</span><span class="text-blue">as</span><span class="text-success">("a").</span>
 
                                                             <br>&nbsp;&nbsp;<span class="text-blue">out</span><span class="text-success">("created").</span><span class="text-blue">in</span><span class="text-success">("created").</span>
 
@@ -336,17 +384,17 @@
                                                     </code>
                                                 </div>
                     </div>
-                     <div class="col-md-12 col-lg-6">
+                    <div class="col-md-12 col-lg-6">
                         <h2 class="ft-30 bold black mb-3 md-md-5">Imperative & Declarative Traversals</h2>
-                        <p>A Gremlin traversal can be written in either an imperative (procedural) manner, a declarative (descriptive) manner, or in a hybrid manner containing both imperative and declarative aspects. An imperative Gremlin traversal tells the traversers how to proceed at each step in the traversal. For instance, the imperative traversal on the right first places a traverser at the vertex denoting Gremlin. That traverser then splits itself across all of Gremlin's collaborators that are not Gremlin himself. Next, the traversers walk to the managers of those collaborators to ultimately be grouped into a manager name count distribution. This traversal is imperative in that it tells the traversers to "go here and then go there" in an explicit, procedural manner.</p>
+                        <p>A Gremlin traversal can be written in either an imperative (procedural) manner, a declarative (descriptive) manner, or in a hybrid manner containing both imperative and declarative aspects. An imperative Gremlin traversal tells the traversers how to proceed at each step in the traversal. For instance, the imperative traversal in the first box first places a traverser at the vertex denoting Gremlin. That traverser then splits itself across all of Gremlin's collaborators that are not Gremlin himself. Next, the traversers walk to the managers of those collaborators to ultimately be grouped into a manager name count distribution. This traversal is imperative in that it tells the traversers to "go here and then go there" in an explicit, procedural manner.</p>
                     </div>
                     
                 </div>
 
                 <div class="row mb-3 mb-md-5">
                     
-                     <div class="col-md-12 col-lg-6 order-2 order-md-1">
-                        <p class="text-lg-end text-start">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 declarative traversal 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.</p>
+                    <div class="col-md-12 col-lg-6 order-2 order-md-1">
+                        <p class="text-lg-end text-start">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 declarative traversal in the second box 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.</p>
                     </div>
                     <div class="col-md-12 col-lg-6 mb-4 mb-lg-0 order-1 order-md-2">
                         <div class="code-box h-100">
@@ -357,9 +405,9 @@
 
                                                             <br>&nbsp;&nbsp;<span class="text-blue">as</span><span class="text-success">("a").</span><span class="text-blue">out</span><span class="text-success">("created").as("b"),</span>
 
-                                                            <br>&nbsp;&nbsp;<span class="text-blue">as</span><span class="text-success">("a").</span><span class="text-blue">in</span><span class="text-success">("created").as("c"),</span>
+                                                            <br>&nbsp;&nbsp;<span class="text-blue">as</span><span class="text-success">("b").</span><span class="text-blue">in</span><span class="text-success">("created").as("c"),</span>
 
-                                                            <br>&nbsp;&nbsp;<span class="text-blue">as</span><span class="text-success">("a").</span><span class="text-blue">in</span><span class="text-success">("manages").as("d"),</span>
+                                                            <br>&nbsp;&nbsp;<span class="text-blue">as</span><span class="text-success">("c").</span><span class="text-blue">in</span><span class="text-success">("manages").as("d"),</span>
 
                                                             <br>&nbsp;&nbsp;&nbsp;<span class="text-blue">where</span><span class="text-success">("a",</span><span class="text-blue">neq</span><span class="text-success">("c"))).</span>
 
@@ -420,9 +468,9 @@
                                                             <br>&nbsp;&nbsp;&nbsp;<span class="text-blue">System.out.printIn</span><span class="text-success">("Average rating :" +</span><span class="text-blue">avg</span><span class="text-success">);</span>
 
 
-                                                              <br>&nbsp;&nbsp;<span class="text-success">}</span>
+                                                              <br>&nbsp;&nbsp;<span class="text-blue">}</span>
 
-                                                                <br>&nbsp;<span class="text-success">}</span>
+                                                                <br>&nbsp;<span class="text-blue">}</span>
                                                              
                                                     </code>
                                                 </div>
@@ -450,7 +498,7 @@
 
                                                             
 
-                                                            <br>&nbsp;&nbsp;&nbsp;<span class="text-blue">System.out.println(</span><span class="text-success">"Average rating"</span><span class="text-purpal">+</span><span class="text-blue">result.next().getDouble(</span><span class="text-success">"AVERAGE"</span><span class="text-blue">)</span>
+                                                            <br>&nbsp;&nbsp;&nbsp;<span class="text-blue">System.out.println(</span><span class="text-success">"Average rating"</span><span class="text-purpal">+</span><span class="text-blue">result.next().getDouble(</span><span class="text-success">"AVERAGE"</span><span class="text-blue">));</span>
 
 
                                                               <br>&nbsp;&nbsp;<span class="text-blue">}</span>
@@ -479,7 +527,7 @@
 
                                                             <br><span class="text-purpal">g</span><span class="text-blue"> =  traversal().withRemote(DriverRemoteConnection.using("<span class="text-success">Localhost</span><span class="text-blue">",</span><span class="text-purpal">8182</span><span class="text-blue">));</span> &nbsp;&nbsp;&nbsp;&nbsp; <span class="comment-text">//remote</span></span>
 
-                                                            <br><span class="text-purpal">g</span><span class="text-blue"> =  traversal().withEmbedded((graph).withComputer(SparkGraphComputer.<span class="text-purpal">class</span><span class="text-blue">);</span> &nbsp;&nbsp;&nbsp; <span class="comment-text">//distributed OLAP</span></span>
+                                                            <br><span class="text-purpal">g</span><span class="text-blue"> =  traversal().withEmbedded(graph).withComputer(SparkGraphComputer.<span class="text-purpal">class</span><span class="text-blue">);</span> &nbsp;&nbsp;&nbsp; <span class="comment-text">//distributed OLAP</span></span>
                                                             
                                                              
                                                     </code>
@@ -541,9 +589,9 @@
                 <div class="row d-flex justify-content-center">
                     <div class="col-md-8 col-lg-6">
                         <div class="ju-box">
-                            <h2 class="ft-40 text-blue bold">Join Us on</h2>
-                            <p class="bold">Join us on our Discord Chat</p>
-                            <a href="https://discord.gg/ndMpKZcBEE"><img src="img/tpvewx.png" class="img-fluid mt-3" alt="img"></a>
+                            <h2 class="ft-40 text-blue bold">Join Us</h2>
+                            <p class="bold">Join us on our Discord Server</p>
+                            <a href="https://discord.gg/kfebyvDM9H"><img src="img/tpvewx.png" class="img-fluid mt-3" alt="img"></a>
                         </div>
                     </div>
                 </div>
@@ -559,9 +607,11 @@
                             <div class="bold ft-25">Apache TinkerPop™</div>
                             <p class="mt-2 mb-4">Apache TinkerPop™ is a graph computing framework for both graph databases (OLTP) and graph analytic systems (OLAP).</p>
                             <ul class="list-unstyled list-inline hover-op-low">
-                                <li class="list-inline-item"><a href="https://discord.gg/ndMpKZcBEE"><img src="img/social/discord.svg" class="img-fluid" alt="img"></a></li>
-                                <li class="list-inline-item"><a href="https://twitter.com/apachetinkerpop"><img src="img/social/twitter-square.svg" class="img-fluid" alt="img"></a></li>
+                                <li class="list-inline-item"><a href="https://discord.gg/kfebyvDM9H"><img src="img/social/discord.svg" class="img-fluid" alt="img"></a></li>
                                 <li class="list-inline-item"><a href="https://github.com/apache/tinkerpop"><img src="img/social/github-box.svg" class="img-fluid" alt="img"></a></li>
+                                <li class="list-inline-item"><a href="https://www.twitch.tv/apachetinkerpop"><img src="img/social/twitch.png" class="img-fluid" alt="img"></a></li>
+                                <li class="list-inline-item"><a href="https://twitter.com/apachetinkerpop"><img src="img/social/twitter-square.svg" class="img-fluid" alt="img"></a></li>
+                                <li class="list-inline-item"><a href="https://www.youtube.com/@apachetinkerpop"><img src="img/social/youtube.png" class="img-fluid" alt="img"></a></li>
                             </ul>
                         </div>
                         <div class="col-md-4 ft-links">
@@ -572,6 +622,7 @@
                                         <li><a href="index.html">Home</a></li>
                                         <li><a href="download.html">Downloads</a></li>
                                         <li><a href="https://tinkerpop.apache.org/docs/current">Documentation</a></li>
+                                        <li><a href="https://privacy.apache.org/policies/privacy-policy-public.html" target="_blank">Privacy Policy</a></li>
                                     </ul>
                                 </div>
                                 <div class="col-lg-6">
@@ -593,7 +644,7 @@
                 <div class="container">
                     <div class="row">
                         <div class="col-12">
-                            Copyright © 2015-2022 The Apache Software Foundation
+                            Copyright © 2015-2023 The Apache Software Foundation
                         </div>
                     </div>
                 </div>
@@ -601,9 +652,7 @@
         </footer>
         <script src="js/jquery-1.11.1.js"></script>
         <script src="js/bootstrap.bundle.min.js"></script>
-      <script src="https://cdnjs.cloudflare.com/ajax/libs/wow/1.1.2/wow.min.js"
-              integrity="sha512-Eak/29OTpb36LLo2r47IpVzPBLXnAMPAVypbSZiZ4Qkf8p/7S/XRG5xp7OKWPPYfJT6metI+IORkR5G8F900+g=="
-              crossorigin="anonymous" referrerpolicy="no-referrer"></script>
+      <script src="js/wow.min.js"></script>
         <script src="js/my.js"></script>
         <script src="js/prism.js"></script>
     </body>
diff --git a/docs/site/home/img/answer-overflow-logo.png b/docs/site/home/img/answer-overflow-logo.png
new file mode 100644
index 0000000..1feb07c
--- /dev/null
+++ b/docs/site/home/img/answer-overflow-logo.png
Binary files differ
diff --git a/docs/site/home/img/community/db.png b/docs/site/home/img/community/db.png
new file mode 100644
index 0000000..7baa379
--- /dev/null
+++ b/docs/site/home/img/community/db.png
Binary files differ
diff --git a/docs/site/home/img/community/tools.png b/docs/site/home/img/community/tools.png
index 8a819eb..7fee280 100644
--- a/docs/site/home/img/community/tools.png
+++ b/docs/site/home/img/community/tools.png
Binary files differ
diff --git a/docs/site/home/img/discord_button.png b/docs/site/home/img/discord-button.png
similarity index 100%
rename from docs/site/home/img/discord_button.png
rename to docs/site/home/img/discord-button.png
Binary files differ
diff --git a/docs/site/home/img/discord_logo.png b/docs/site/home/img/discord-logo.png
similarity index 100%
rename from docs/site/home/img/discord_logo.png
rename to docs/site/home/img/discord-logo.png
Binary files differ
diff --git a/docs/site/home/img/jira-logo.png b/docs/site/home/img/jira-logo.png
new file mode 100644
index 0000000..b768d16
--- /dev/null
+++ b/docs/site/home/img/jira-logo.png
Binary files differ
diff --git a/docs/site/home/img/link-arrow.svg b/docs/site/home/img/link-arrow.svg
new file mode 100644
index 0000000..62f0935
--- /dev/null
+++ b/docs/site/home/img/link-arrow.svg
@@ -0,0 +1,11 @@
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50.000000 50.000000"
+     preserveAspectRatio="xMidYMid meet">
+    <g transform="translate(0.000000,50.000000) scale(0.100000,-0.100000)" fill="#147aa4" stroke="none">
+        <path d="M45 447 c-3 -7 -4 -100 -3 -207 l3 -195 205 0 205 0 0 205 0 205
+-203 3 c-159 2 -204 0 -207 -11z m395 -197 l0 -190 -190 0 -190 0 0 190 0 190
+190 0 190 0 0 -190z"/>
+        <path d="M240 400 c0 -6 29 -10 67 -10 l68 0 -110 -110 c-60 -60 -106 -113
+-102 -117 4 -4 57 42 117 102 l110 110 0 -68 c0 -38 4 -67 10 -67 6 0 10 35
+10 85 l0 85 -85 0 c-50 0 -85 -4 -85 -10z"/>
+    </g>
+</svg>
diff --git a/docs/site/home/img/mail.png b/docs/site/home/img/mail.png
new file mode 100644
index 0000000..86ce9a6
--- /dev/null
+++ b/docs/site/home/img/mail.png
Binary files differ
diff --git a/docs/site/home/img/social/twitch.png b/docs/site/home/img/social/twitch.png
new file mode 100644
index 0000000..721f349
--- /dev/null
+++ b/docs/site/home/img/social/twitch.png
Binary files differ
diff --git a/docs/site/home/img/social/youtube.png b/docs/site/home/img/social/youtube.png
new file mode 100644
index 0000000..45d6d4a
--- /dev/null
+++ b/docs/site/home/img/social/youtube.png
Binary files differ
diff --git a/docs/site/home/img/stack-overflow-logo.png b/docs/site/home/img/stack-overflow-logo.png
new file mode 100644
index 0000000..d29cbc1
--- /dev/null
+++ b/docs/site/home/img/stack-overflow-logo.png
Binary files differ
diff --git a/docs/site/home/img/tools.png b/docs/site/home/img/tools.png
new file mode 100644
index 0000000..1942e5e
--- /dev/null
+++ b/docs/site/home/img/tools.png
Binary files differ
diff --git a/docs/site/home/img/twitch-logo.png b/docs/site/home/img/twitch-logo.png
new file mode 100644
index 0000000..bdc98e7
--- /dev/null
+++ b/docs/site/home/img/twitch-logo.png
Binary files differ
diff --git a/docs/site/home/img/youtube-logo.png b/docs/site/home/img/youtube-logo.png
new file mode 100644
index 0000000..bd762d7
--- /dev/null
+++ b/docs/site/home/img/youtube-logo.png
Binary files differ
diff --git a/docs/site/home/index.html b/docs/site/home/index.html
index 447f373..e4f9745 100644
--- a/docs/site/home/index.html
+++ b/docs/site/home/index.html
@@ -19,22 +19,33 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
     <link href="img/favicon.png" rel="shortcut icon"/>
-    <title>Apache TinkerPop</title>
+    <title>Apache TinkerPop: Home</title>
     <meta name="description" content="">
     <meta name="keywords" content="">
     <link href="css/bootstrap.min.css" rel="stylesheet">
-    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css"
-          integrity="sha512-5A8nwdMOWrSz20fDsjczgUidUBR8liPYU+WymTZP1lmY9G6Oc7HlZv156XqnsgNUzTyMefFTcsFH/tnJE/+xBg=="
-          crossorigin="anonymous" referrerpolicy="no-referrer"/>
+    <link href="css/font-awesome.css" rel="stylesheet"/>
     <link href="css/custome.css" rel="stylesheet">
     <link href="css/responsive.css" rel="stylesheet">
-    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.1/animate.css"
-          integrity="sha512-K2J6Yt6ElUYEMPcTr0wm555AAyiqkgYiUgPIW18FT88/aYSNDk0EvGjsln/TEu3ee/jaHf0xoXzFppSbBtUXbQ=="
-          crossorigin="anonymous" referrerpolicy="no-referrer"/>
+    <link href="css/animate.css" rel="stylesheet"/>
     <link href="css/prism.css" rel="stylesheet">
-    <link rel="preconnect" href="https://fonts.googleapis.com">
-    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-    <link href="https://fonts.googleapis.com/css2?family=Raleway:wght@400;500;600;700&display=swap" rel="stylesheet">
+    <link href="css/fonts.css" rel="stylesheet">
+    <!-- Matomo -->
+    <script>
+        var _paq = window._paq = window._paq || [];
+        /* We explicitly disable cookie tracking to avoid privacy issues */
+        _paq.push(['disableCookies']);
+        /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
+        _paq.push(['trackPageView']);
+        _paq.push(['enableLinkTracking']);
+        (function() {
+            var u="https://analytics.apache.org/";
+            _paq.push(['setTrackerUrl', u+'matomo.php']);
+            _paq.push(['setSiteId', '27']);
+            var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
+            g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
+        })();
+    </script>
+    <!-- End Matomo Code -->
 </head>
 <body>
 <!-- header -->
@@ -58,6 +69,21 @@
                         <li class="nav-item">
                             <a class="nav-link" href="download.html">Download</a>
                         </li>
+
+                        <li class="nav-item dropdown">
+                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown4" role="button" data-bs-toggle="dropdown" aria-expanded="false">
+                                Tools
+                            </a>
+                            <ul class="dropdown-menu" aria-labelledby="navbarDropdown4">
+                                <li><a class="dropdown-item" href="providers.html">Graph Systems</a></li>
+                                <li><a class="dropdown-item" href="community.html">Languages and Tools</a></li>
+                                <li><hr class="dropdown-divider"></li>
+                                <li><a class="dropdown-item" href="https://gremlify.com/">Gremlify: Try Gremlin</a></li>
+                                <li><a class="dropdown-item" href="https://tinkerpop.apache.org/gremlint">Gremlint: Lint Gremlin</a></li>
+                                <li><a class="dropdown-item" href="https://www.gremlator.com/">Gremlator: Translate Gremlin</a></li>
+                            </ul>
+                        </li>
+
                         <li class="nav-item dropdown">
                             <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
                                data-bs-toggle="dropdown" aria-expanded="false">
@@ -80,6 +106,7 @@
                             </ul>
 
                         </li>
+
                         <li class="nav-item dropdown">
                             <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown1" role="button"
                                data-bs-toggle="dropdown" aria-expanded="false">
@@ -109,48 +136,31 @@
 
                         </li>
                         <li class="nav-item dropdown">
-                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown3" role="button"
-                               data-bs-toggle="dropdown" aria-expanded="false">
+                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown3" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                                 Community
                             </a>
                             <ul class="dropdown-menu" aria-labelledby="navbarDropdown3">
-                                <li><a class="dropdown-item" href="https://groups.google.com/group/gremlin-users">User
-                                    Mailing List</a></li>
-                                <li><a class="dropdown-item"
-                                       href="https://lists.apache.org/list.html?dev@tinkerpop.apache.org">Developer
-                                    Mailing List</a></li>
-                                <li><a class="dropdown-item" href="https://discord.gg/ndMpKZcBEE" target="_blank"><img
-                                        src="img/discord_logo.png" class="nav-icon">Join us on Discord</a></li>
-                                <li><a class="dropdown-item" href="https://issues.apache.org/jira/browse/TINKERPOP/">Issue
-                                    Tracker</a></li>
-                                <li><a class="dropdown-item"
-                                       href="https://tinkerpop.apache.org/docs/current/dev/developer/#_contributing">Contributing</a>
-                                </li>
-                                <li><a class="dropdown-item" href="providers.html">Data System Support</a></li>
-                                <li><a class="dropdown-item" href="community.html">Languages and Tools</a></li>
-                                <li><a class="dropdown-item"
-                                       href="https://tinkerpop.apache.org/docs/current/dev/provider/#policies">Policies</a>
-                                </li>
-                                <li>
-                                    <hr class="dropdown-divider">
-                                </li>
-                                <li><a class="dropdown-item" href="https://github.com/apache/tinkerpop/"><img
-                                        src="img/github-logo.png" class="nav-icon">GitHub</a></li>
-                                <li><a class="dropdown-item" href="https://twitter.com/apachetinkerpop"><img
-                                        src="img/twitter-logo.png" class="nav-icon">Twitter</a></li>
+                                <li><a class="dropdown-item" href="https://discord.gg/kfebyvDM9H" target="_blank"><img src="img/discord-logo.png" class="nav-icon"/>Discord</a></li>
+                                <li><a class="dropdown-item" href="https://www.answeroverflow.com/c/838910279550238720"><img src="img/answer-overflow-logo.png" class="nav-icon"/>Answer Overflow</a></li>
+                                <li><a class="dropdown-item" href="https://stackoverflow.com/questions/tagged/gremlin"><img src="img/stack-overflow-logo.png" class="nav-icon"/>Stack Overflow</a></li>
+                                <li><a class="dropdown-item" href="https://groups.google.com/group/gremlin-users"><img src="img/mail.png" class="nav-icon"/>User Mailing List</a></li>
+                                <li><a class="dropdown-item" href="https://lists.apache.org/list.html?dev@tinkerpop.apache.org"><img src="img/mail.png" class="nav-icon"/>Developer Mailing List</a></li>
+                                <li><a class="dropdown-item" href="https://issues.apache.org/jira/browse/TINKERPOP/"><img src="img/jira-logo.png" class="nav-icon"/>Issue Tracker</a></li>
+                                <li><a class="dropdown-item" href="https://github.com/apache/tinkerpop/"><img src="img/github-logo.png" class="nav-icon"/>GitHub</a></li>
+                                <li><a class="dropdown-item" href="https://www.twitch.tv/apachetinkerpop"><img src="img/twitch-logo.png" class="nav-icon"/>Twitch</a></li>
+                                <li><a class="dropdown-item" href="https://twitter.com/apachetinkerpop"><img src="img/twitter-logo.png" class="nav-icon"/>Twitter</a></li>
+                                <li><a class="dropdown-item" href="https://www.youtube.com/@apachetinkerpop"><img src="img/youtube-logo.png" class="nav-icon"/>YouTube</a></li>
+                                <li><hr class="dropdown-divider"></li>
+                                <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/dev/developer/#_contributing">Contributing</a></li>
+                                <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/dev/provider/#policies">Policies</a></li>
                             </ul>
-
-                        </li>
-
-                        <li class="nav-item">
-                            <a class="nav-link" href="https://tinkerpop.apache.org/gremlint/">Gremlint</a>
                         </li>
                         <li class="nav-item dropdown">
-                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown4" role="button"
+                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown5" role="button"
                                data-bs-toggle="dropdown" aria-expanded="false">
                                 Apache Software
                             </a>
-                            <ul class="dropdown-menu" aria-labelledby="navbarDropdown4">
+                            <ul class="dropdown-menu" aria-labelledby="navbarDropdown5">
                                 <li><a class="dropdown-item" href="https://www.apache.org/">Apache Homepage</a></li>
                                 <li><a class="dropdown-item" href="https://www.apache.org/licenses/">License</a></li>
                                 <li><a class="dropdown-item"
@@ -179,7 +189,7 @@
                 <h1 class="ft-40 bold black mb-3">Apache TinkerPop™</h1>
                 <p>Apache TinkerPop™ is a graph computing framework for both graph databases (OLTP) and graph analytic
                     systems (OLAP).</p>
-                <a href="https://discord.gg/ndMpKZcBEE" target="_blank"><img src="img/discord_button.png" alt="img"
+                <a href="https://discord.gg/kfebyvDM9H" target="_blank"><img src="img/discord-button.png" alt="img"
                                                                              class="img-fluid"></a>
             </div>
         </div>
@@ -200,30 +210,30 @@
                 <div class="dd-box">
                     <div class="text-center">
                         <h2 class="ft-30 bold black mb-2">Downloads & Documentation</h2>
-                        <p class="mb-3 mb-md-5 medium ">Released: 4-April-2022</p>
+                        <p class="mb-3 mb-md-5 medium ">Released: 12-May-2023</p>
                     </div>
                     <div class="row">
                         <div class="col-lg-6 border-right text-center">
-                            <h3 class="ft-25 bold black mb-4">TinkerPop 3.6.0 Downloads</h3>
+                            <h3 class="ft-25 bold black mb-6">TinkerPop 3.6.4 Downloads</h3>
                             <div class="row">
                                 <div class="col-md-4 mb-3">
                                     <img src="img/group-24.svg" class="img-fluid mb-2" alt="img"><br>
                                     <a class="text-blue"
-                                       href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.6.0/apache-tinkerpop-gremlin-console-3.6.0-bin.zip"><img
+                                       href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.6.4/apache-tinkerpop-gremlin-console-3.6.4-bin.zip"><img
                                             src="img/download-cloud-line.svg" class="me-2 img-fluid" alt="img">Gremlin
                                         Console</a>
                                 </div>
                                 <div class="col-md-4 mb-3">
                                     <img src="img/group-25.svg" class="img-fluid mb-2" alt="img"><br>
                                     <a class="text-blue"
-                                       href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.6.0/apache-tinkerpop-gremlin-server-3.6.0-bin.zip"><img
+                                       href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.6.4/apache-tinkerpop-gremlin-server-3.6.4-bin.zip"><img
                                             src="img/download-cloud-line.svg" class="me-2 img-fluid" alt="img">Gremlin
                                         Server</a>
                                 </div>
                                 <div class="col-md-4 mb-3">
                                     <img src="img/group-26.svg" class="img-fluid mb-2" alt="img"><br>
                                     <a class="text-blue"
-                                       href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.6.0/apache-tinkerpop-3.6.0-src.zip"><img
+                                       href="https://www.apache.org/dyn/closer.lua/tinkerpop/3.6.4/apache-tinkerpop-3.6.4-src.zip"><img
                                             src="img/download-cloud-line.svg" class="me-2 img-fluid"
                                             alt="img">Source</a>
                                 </div>
@@ -233,7 +243,6 @@
                             <h3 class="ft-25 bold black mb-4">Documentation</h3>
                             <div class="row">
                                 <div class="col-md-6 mb-3">
-
                                     <div class="dropdown text-start">
                                         <button class="btn btn-theme btn-cust w-100 dropdown-toggle text-start"
                                                 type="button" id="dropdownMenuButton1" data-bs-toggle="dropdown"
@@ -275,7 +284,59 @@
                         </div>
                     </div>
 
+                    <div class="row">
+                        <div class="col-2 mb-1">
+                            &nbsp;
+                        </div>
+                        <div class="col-1 mb-1">
+                            <a href="community.html#lang-go"><img src="img/community/go.png" class="img-fluid me-3" title="Go" alt="Go"></a>
+                        </div>
+                        <div class="col-1 mb-1">
+                            <a href="community.html#lang-groovy"><img src="img/community/groovy.png" class="img-fluid me-3" title="Groovy" alt="Groovy"></a>
+                        </div>
+                        <div class="col-1 mb-1">
+                            <a href="community.html#lang-java"><img src="img/community/java.png" class="img-fluid me-3" title="Java" alt="Java"></a>
+                        </div>
+                        <div class="col-1 mb-1">
+                            <a href="community.html#lang-javascript"><img src="img/community/javascript.png" class="img-fluid me-3" title="Javascript" alt="Javascript" width="44"></a>
+                        </div>
+                        <div class="col-1 mb-1">
+                            <a href="community.html#lang-csharp"><img src="img/community/c-sharp-logo-png.png" class="img-fluid me-3" title="C#" alt="C#"></a>
+                        </div>
+                        <div class="col-1 mb-1">
+                            <a href="community.html#lang-python"><img src="img/community/python.png" class="img-fluid me-3" title="Python" alt="Python"></a>
+                        </div>
+                        <div class="col-1 mb-1">
+                            <a href="community.html"><img src="img/tools.png" class="img-fluid me-3" title="More Languages and Tools" alt="More Languages and Tools" width="40"></a>
+                        </div>
+                        <div class="col-1 mb-1">
+                            <a href="providers.html"><img src="img/community/db.png" class="img-fluid me-3" title="Graph Systems" alt="Graph Systems"></a>
+                        </div>
+                        <div class="col-2 mb-1">
+                            &nbsp;
+                        </div>
+                    </div>
 
+                    <div class="row">
+                        <div class="col-3">
+                            &nbsp;
+                        </div>
+                        <div class="col-md-2 mt-3">
+                            <a class="text-blue" href="https://gremlify.com">
+                                <img src="img/link-arrow.svg" class="me-2 img-fluid" alt="img" style="max-height: 16px"/>Try Gremlin</a>
+                        </div>
+                        <div class="col-md-2 mt-3">
+                            <a class="text-blue" href="https://gremlint.com">
+                                <img src="img/link-arrow.svg" class="me-2 img-fluid" alt="img" style="max-height: 16px"/>Lint Gremlin</a>
+                        </div>
+                        <div class="col-md-2 mt-3">
+                            <a class="text-blue" href="https://www.gremlator.com">
+                                <img src="img/link-arrow.svg" class="me-2 img-fluid" alt="img" style="max-height: 16px"/>Translate Gremlin</a>
+                        </div>
+                        <div class="col-3 mt-3">
+                            &nbsp;
+                        </div>
+                    </div>
 
                 </div>
             </div>
@@ -401,8 +462,6 @@
                 <a class="btn btn-theme btn-cust" href="gremlin.html"><img src="img/link.svg" class="img-fluid me-2"
                                                                            alt="img">Learn More</a>
             </div>
-
-
         </div>
     </div>
 </div>
@@ -507,8 +566,8 @@
                 <div class="col">
                     <div class="com-box">
                         <div>
-                            <a class="text-blue " href="https://discord.gg/ndMpKZcBEE"><img src="img/discord.png" class="img-fluid mb-4 " alt="img"></a><br>
-                            <a class="text-blue " href="https://discord.gg/ndMpKZcBEE">Discord</a>
+                            <a class="text-blue " href="https://discord.gg/kfebyvDM9H"><img src="img/discord.png" class="img-fluid mb-4 " alt="img"></a><br>
+                            <a class="text-blue " href="https://discord.gg/kfebyvDM9H">Discord</a>
                         </div>
                     </div>
                 </div>
@@ -616,7 +675,7 @@
                                     <div class="mb-3">
                                         <p class="mb-0"><a class="medium text-blue"
                                                            href="https://ketrinadrawsalot.tumblr.com/" target="_blank">
-                                            Ketrina Yim</a><span class="medium">(Committer)</span></p>
+                                            Ketrina Thompson</a><span class="medium">(Committer)</span></p>
                                         <p class="mb-0"><span class="medium">Year : 2009</span></p>
                                         <p class="mb-0">Illustrator, creator of Gremlin and his merry band of
                                             robots.</p>
@@ -669,7 +728,7 @@
                                     <div class="mb-3">
                                         <p class="mb-0"><a class="medium text-blue"
                                                            href="https://www.linkedin.com/in/divijvaidya/"
-                                                           target="_blank">Divij Vaidya </a><span class="medium">(Committer)</span>
+                                                           target="_blank">Divij Vaidya </a><span class="medium">(PMC)</span>
                                         </p>
                                         <p class="mb-0"><span class="medium">Year : 2019</span></p>
                                         <p class="mb-0">Gremlin server-client interaction.</p>
@@ -706,6 +765,65 @@
                                         <p class="mb-0">Gremlin language and general core development</p>
                                     </div>
                                 </div>
+                                <div class="col-lg-6">
+                                    <div class="mb-3">
+                                        <p class="mb-0"><a class="medium text-blue"
+                                                           href="https://www.linkedin.com/in/davebechberger/"
+                                                           target="_blank">Dave Bechberger </a><span class="medium">(Committer)</span>
+                                        </p>
+                                        <p class="mb-0"><span class="medium">Year : 2022</span></p>
+                                        <p class="mb-0">Gremlin language, documentation, mailing list and Discord support</p>
+                                    </div>
+                                </div>
+                                <div class="col-lg-6">
+                                    <div class="mb-3">
+                                        <p class="mb-0"><a class="medium text-blue" href="https://www.linkedin.com/in/simon-zhao-69a792ab/"
+                                                           target="_blank">Simon Zhao </a><span class="medium">(Committer)</span>
+                                        </p>
+                                        <p class="mb-0"><span class="medium">Year : 2022</span></p>
+                                        <p class="mb-0">Golang GLV</p>
+                                    </div>
+                                </div>
+                                <div class="col-lg-6">
+                                    <div class="mb-3">
+                                        <p class="mb-0"><a class="medium text-blue" href="https://www.linkedin.com/in/xiazcy/"
+                                                           target="_blank">Yang Xia </a><span class="medium">(PMC)</span>
+                                        </p>
+                                        <p class="mb-0"><span class="medium">Year : 2022</span></p>
+                                        <p class="mb-0">Go GLV development, Docker and Windows build improvements</p>
+                                    </div>
+                                </div>
+                                <div class="col-lg-6">
+                                    <div class="mb-3">
+                                        <p class="mb-0">
+                                            <a class="medium text-blue" 
+                                               href="https://www.linkedin.com/in/valentyn-kahamlyk-2bb4874b/"
+                                               target="_blank">Valentyn Kahamlyk </a><span class="medium">(Committer)</span>
+                                        </p>
+                                        <p class="mb-0"><span class="medium">Year : 2022</span></p>
+                                        <p class="mb-0">Go and Python GLV development, </p>
+                                    </div>
+                                </div>
+                                <div class="col-lg-6">
+                                    <div class="mb-3">
+                                        <p class="mb-0">
+                                            <a class="medium text-blue" 
+                                               href="https://github.com/L0Lmaker"
+                                               target="_blank">Rithin Kumar  </a><span class="medium">(Committer)</span>
+                                        </p>
+                                        <p class="mb-0"><span class="medium">Year : 2022</span></p>
+                                        <p class="mb-0">Golang GLV</p>
+                                    </div>
+                                </div>
+                                <div class="col-lg-6">
+                                    <div class="mb-3">
+                                        <p class="mb-0"><a class="medium text-blue" href="https://github.com/kenhuuu"
+                                                           target="_blank">Ken Hu </a><span class="medium">(Committer)</span>
+                                        </p>
+                                        <p class="mb-0"><span class="medium">Year : 2023</span></p>
+                                        <p class="mb-0">General project maintenance</p>
+                                    </div>
+                                </div>
                             </div>
                         </div>
                         <div class="tab-pane fade" id="pills-inactive" role="tabpanel"
@@ -872,9 +990,9 @@
         <div class="row d-flex justify-content-center">
             <div class="col-md-8 col-lg-6">
                 <div class="ju-box">
-                    <h2 class="ft-40 text-blue bold">Join Us on</h2>
-                    <p class="bold">Join us on our Discord Chat</p>
-                    <a href="https://discord.gg/ndMpKZcBEE"><img src="img/tpvewx.png" class="img-fluid mt-3" alt="img"></a>
+                    <h2 class="ft-40 text-blue bold">Join Us</h2>
+                    <p class="bold">Join us on our Discord Server</p>
+                    <a href="https://discord.gg/kfebyvDM9H"><img src="img/tpvewx.png" class="img-fluid mt-3" alt="img"></a>
                 </div>
             </div>
         </div>
@@ -888,15 +1006,13 @@
             <div class="row">
                 <div class="col-md-4">
                     <div class="bold ft-25">Apache TinkerPop™</div>
-                    <p class="mt-2 mb-4">Apache TinkerPop™ is a graph computing framework for both graph databases
-                        (OLTP) and graph analytic systems (OLAP).</p>
+                    <p class="mt-2 mb-4">Apache TinkerPop™ is a graph computing framework for both graph databases (OLTP) and graph analytic systems (OLAP).</p>
                     <ul class="list-unstyled list-inline hover-op-low">
-                        <li class="list-inline-item"><a href="https://discord.gg/ndMpKZcBEE"><img
-                                src="img/social/discord.svg" class="img-fluid" alt="img"></a></li>
-                        <li class="list-inline-item"><a href="https://twitter.com/apachetinkerpop"><img
-                                src="img/social/twitter-square.svg" class="img-fluid" alt="img"></a></li>
-                        <li class="list-inline-item"><a href="https://github.com/apache/tinkerpop"><img
-                                src="img/social/github-box.svg" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://discord.gg/kfebyvDM9H"><img src="img/social/discord.svg" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://github.com/apache/tinkerpop"><img src="img/social/github-box.svg" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://www.twitch.tv/apachetinkerpop"><img src="img/social/twitch.png" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://twitter.com/apachetinkerpop"><img src="img/social/twitter-square.svg" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://www.youtube.com/@apachetinkerpop"><img src="img/social/youtube.png" class="img-fluid" alt="img"></a></li>
                     </ul>
                 </div>
                 <div class="col-md-4 ft-links">
@@ -907,6 +1023,7 @@
                                 <li><a href="index.html">Home</a></li>
                                 <li><a href="download.html">Downloads</a></li>
                                 <li><a href="https://tinkerpop.apache.org/docs/current">Documentation</a></li>
+                                <li><a href="https://privacy.apache.org/policies/privacy-policy-public.html" target="_blank">Privacy Policy</a></li>
                             </ul>
                         </div>
                         <div class="col-lg-6">
@@ -931,7 +1048,7 @@
         <div class="container">
             <div class="row">
                 <div class="col-12">
-                    Copyright © 2015-2022 The Apache Software Foundation
+                    Copyright © 2015-2023 The Apache Software Foundation
                 </div>
             </div>
         </div>
@@ -939,9 +1056,7 @@
 </footer>
 <script src="js/jquery-1.11.1.js"></script>
 <script src="js/bootstrap.bundle.min.js"></script>
-<script src="https://cdnjs.cloudflare.com/ajax/libs/wow/1.1.2/wow.min.js"
-        integrity="sha512-Eak/29OTpb36LLo2r47IpVzPBLXnAMPAVypbSZiZ4Qkf8p/7S/XRG5xp7OKWPPYfJT6metI+IORkR5G8F900+g=="
-        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
+<script src="js/wow.min.js"></script>
 <script src="js/my.js"></script>
 <script src="js/prism.js"></script>
 </body>
diff --git a/docs/site/home/js/wow.min.js b/docs/site/home/js/wow.min.js
new file mode 100644
index 0000000..a692251
--- /dev/null
+++ b/docs/site/home/js/wow.min.js
@@ -0,0 +1,2 @@
+/*! WOW - v1.1.2 - 2015-04-07
+* Copyright (c) 2015 Matthieu Aussaguel; Licensed MIT */(function(){var a,b,c,d,e,f=function(a,b){return function(){return a.apply(b,arguments)}},g=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};b=function(){function a(){}return a.prototype.extend=function(a,b){var c,d;for(c in b)d=b[c],null==a[c]&&(a[c]=d);return a},a.prototype.isMobile=function(a){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(a)},a.prototype.createEvent=function(a,b,c,d){var e;return null==b&&(b=!1),null==c&&(c=!1),null==d&&(d=null),null!=document.createEvent?(e=document.createEvent("CustomEvent"),e.initCustomEvent(a,b,c,d)):null!=document.createEventObject?(e=document.createEventObject(),e.eventType=a):e.eventName=a,e},a.prototype.emitEvent=function(a,b){return null!=a.dispatchEvent?a.dispatchEvent(b):b in(null!=a)?a[b]():"on"+b in(null!=a)?a["on"+b]():void 0},a.prototype.addEvent=function(a,b,c){return null!=a.addEventListener?a.addEventListener(b,c,!1):null!=a.attachEvent?a.attachEvent("on"+b,c):a[b]=c},a.prototype.removeEvent=function(a,b,c){return null!=a.removeEventListener?a.removeEventListener(b,c,!1):null!=a.detachEvent?a.detachEvent("on"+b,c):delete a[b]},a.prototype.innerHeight=function(){return"innerHeight"in window?window.innerHeight:document.documentElement.clientHeight},a}(),c=this.WeakMap||this.MozWeakMap||(c=function(){function a(){this.keys=[],this.values=[]}return a.prototype.get=function(a){var b,c,d,e,f;for(f=this.keys,b=d=0,e=f.length;e>d;b=++d)if(c=f[b],c===a)return this.values[b]},a.prototype.set=function(a,b){var c,d,e,f,g;for(g=this.keys,c=e=0,f=g.length;f>e;c=++e)if(d=g[c],d===a)return void(this.values[c]=b);return this.keys.push(a),this.values.push(b)},a}()),a=this.MutationObserver||this.WebkitMutationObserver||this.MozMutationObserver||(a=function(){function a(){"undefined"!=typeof console&&null!==console&&console.warn("MutationObserver is not supported by your browser."),"undefined"!=typeof console&&null!==console&&console.warn("WOW.js cannot detect dom mutations, please call .sync() after loading new content.")}return a.notSupported=!0,a.prototype.observe=function(){},a}()),d=this.getComputedStyle||function(a){return this.getPropertyValue=function(b){var c;return"float"===b&&(b="styleFloat"),e.test(b)&&b.replace(e,function(a,b){return b.toUpperCase()}),(null!=(c=a.currentStyle)?c[b]:void 0)||null},this},e=/(\-([a-z]){1})/g,this.WOW=function(){function e(a){null==a&&(a={}),this.scrollCallback=f(this.scrollCallback,this),this.scrollHandler=f(this.scrollHandler,this),this.resetAnimation=f(this.resetAnimation,this),this.start=f(this.start,this),this.scrolled=!0,this.config=this.util().extend(a,this.defaults),this.animationNameCache=new c,this.wowEvent=this.util().createEvent(this.config.boxClass)}return e.prototype.defaults={boxClass:"wow",animateClass:"animated",offset:0,mobile:!0,live:!0,callback:null},e.prototype.init=function(){var a;return this.element=window.document.documentElement,"interactive"===(a=document.readyState)||"complete"===a?this.start():this.util().addEvent(document,"DOMContentLoaded",this.start),this.finished=[]},e.prototype.start=function(){var b,c,d,e;if(this.stopped=!1,this.boxes=function(){var a,c,d,e;for(d=this.element.querySelectorAll("."+this.config.boxClass),e=[],a=0,c=d.length;c>a;a++)b=d[a],e.push(b);return e}.call(this),this.all=function(){var a,c,d,e;for(d=this.boxes,e=[],a=0,c=d.length;c>a;a++)b=d[a],e.push(b);return e}.call(this),this.boxes.length)if(this.disabled())this.resetStyle();else for(e=this.boxes,c=0,d=e.length;d>c;c++)b=e[c],this.applyStyle(b,!0);return this.disabled()||(this.util().addEvent(window,"scroll",this.scrollHandler),this.util().addEvent(window,"resize",this.scrollHandler),this.interval=setInterval(this.scrollCallback,50)),this.config.live?new a(function(a){return function(b){var c,d,e,f,g;for(g=[],c=0,d=b.length;d>c;c++)f=b[c],g.push(function(){var a,b,c,d;for(c=f.addedNodes||[],d=[],a=0,b=c.length;b>a;a++)e=c[a],d.push(this.doSync(e));return d}.call(a));return g}}(this)).observe(document.body,{childList:!0,subtree:!0}):void 0},e.prototype.stop=function(){return this.stopped=!0,this.util().removeEvent(window,"scroll",this.scrollHandler),this.util().removeEvent(window,"resize",this.scrollHandler),null!=this.interval?clearInterval(this.interval):void 0},e.prototype.sync=function(){return a.notSupported?this.doSync(this.element):void 0},e.prototype.doSync=function(a){var b,c,d,e,f;if(null==a&&(a=this.element),1===a.nodeType){for(a=a.parentNode||a,e=a.querySelectorAll("."+this.config.boxClass),f=[],c=0,d=e.length;d>c;c++)b=e[c],g.call(this.all,b)<0?(this.boxes.push(b),this.all.push(b),this.stopped||this.disabled()?this.resetStyle():this.applyStyle(b,!0),f.push(this.scrolled=!0)):f.push(void 0);return f}},e.prototype.show=function(a){return this.applyStyle(a),a.className=a.className+" "+this.config.animateClass,null!=this.config.callback&&this.config.callback(a),this.util().emitEvent(a,this.wowEvent),this.util().addEvent(a,"animationend",this.resetAnimation),this.util().addEvent(a,"oanimationend",this.resetAnimation),this.util().addEvent(a,"webkitAnimationEnd",this.resetAnimation),this.util().addEvent(a,"MSAnimationEnd",this.resetAnimation),a},e.prototype.applyStyle=function(a,b){var c,d,e;return d=a.getAttribute("data-wow-duration"),c=a.getAttribute("data-wow-delay"),e=a.getAttribute("data-wow-iteration"),this.animate(function(f){return function(){return f.customStyle(a,b,d,c,e)}}(this))},e.prototype.animate=function(){return"requestAnimationFrame"in window?function(a){return window.requestAnimationFrame(a)}:function(a){return a()}}(),e.prototype.resetStyle=function(){var a,b,c,d,e;for(d=this.boxes,e=[],b=0,c=d.length;c>b;b++)a=d[b],e.push(a.style.visibility="visible");return e},e.prototype.resetAnimation=function(a){var b;return a.type.toLowerCase().indexOf("animationend")>=0?(b=a.target||a.srcElement,b.className=b.className.replace(this.config.animateClass,"").trim()):void 0},e.prototype.customStyle=function(a,b,c,d,e){return b&&this.cacheAnimationName(a),a.style.visibility=b?"hidden":"visible",c&&this.vendorSet(a.style,{animationDuration:c}),d&&this.vendorSet(a.style,{animationDelay:d}),e&&this.vendorSet(a.style,{animationIterationCount:e}),this.vendorSet(a.style,{animationName:b?"none":this.cachedAnimationName(a)}),a},e.prototype.vendors=["moz","webkit"],e.prototype.vendorSet=function(a,b){var c,d,e,f;d=[];for(c in b)e=b[c],a[""+c]=e,d.push(function(){var b,d,g,h;for(g=this.vendors,h=[],b=0,d=g.length;d>b;b++)f=g[b],h.push(a[""+f+c.charAt(0).toUpperCase()+c.substr(1)]=e);return h}.call(this));return d},e.prototype.vendorCSS=function(a,b){var c,e,f,g,h,i;for(h=d(a),g=h.getPropertyCSSValue(b),f=this.vendors,c=0,e=f.length;e>c;c++)i=f[c],g=g||h.getPropertyCSSValue("-"+i+"-"+b);return g},e.prototype.animationName=function(a){var b;try{b=this.vendorCSS(a,"animation-name").cssText}catch(c){b=d(a).getPropertyValue("animation-name")}return"none"===b?"":b},e.prototype.cacheAnimationName=function(a){return this.animationNameCache.set(a,this.animationName(a))},e.prototype.cachedAnimationName=function(a){return this.animationNameCache.get(a)},e.prototype.scrollHandler=function(){return this.scrolled=!0},e.prototype.scrollCallback=function(){var a;return!this.scrolled||(this.scrolled=!1,this.boxes=function(){var b,c,d,e;for(d=this.boxes,e=[],b=0,c=d.length;c>b;b++)a=d[b],a&&(this.isVisible(a)?this.show(a):e.push(a));return e}.call(this),this.boxes.length||this.config.live)?void 0:this.stop()},e.prototype.offsetTop=function(a){for(var b;void 0===a.offsetTop;)a=a.parentNode;for(b=a.offsetTop;a=a.offsetParent;)b+=a.offsetTop;return b},e.prototype.isVisible=function(a){var b,c,d,e,f;return c=a.getAttribute("data-wow-offset")||this.config.offset,f=window.pageYOffset,e=f+Math.min(this.element.clientHeight,this.util().innerHeight())-c,d=this.offsetTop(a),b=d+a.clientHeight,e>=d&&b>=f},e.prototype.util=function(){return null!=this._util?this._util:this._util=new b},e.prototype.disabled=function(){return!this.config.mobile&&this.util().isMobile(navigator.userAgent)},e}()}).call(this);
\ No newline at end of file
diff --git a/docs/site/home/providers.html b/docs/site/home/providers.html
index 77a7a21..3cddc92 100644
--- a/docs/site/home/providers.html
+++ b/docs/site/home/providers.html
@@ -19,21 +19,31 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
     <link href="img/favicon.png" rel="shortcut icon"/>
-    <title>Apache TinkerPop</title>
+    <title>Apache TinkerPop: Providers</title>
     <meta name="description" content="">
     <meta name="keywords" content="">
     <link href="css/bootstrap.min.css" rel="stylesheet">
-    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css"
-          integrity="sha512-5A8nwdMOWrSz20fDsjczgUidUBR8liPYU+WymTZP1lmY9G6Oc7HlZv156XqnsgNUzTyMefFTcsFH/tnJE/+xBg=="
-          crossorigin="anonymous" referrerpolicy="no-referrer"/>
+    <link href="css/font-awesome.css" rel="stylesheet"/>
     <link href="css/custome.css" rel="stylesheet">
     <link href="css/responsive.css" rel="stylesheet">
-    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.1/animate.css"
-          integrity="sha512-K2J6Yt6ElUYEMPcTr0wm555AAyiqkgYiUgPIW18FT88/aYSNDk0EvGjsln/TEu3ee/jaHf0xoXzFppSbBtUXbQ=="
-          crossorigin="anonymous" referrerpolicy="no-referrer"/>
-    <link rel="preconnect" href="https://fonts.googleapis.com">
-    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-    <link href="https://fonts.googleapis.com/css2?family=Raleway:wght@400;500;600;700&display=swap" rel="stylesheet">
+    <link href="css/animate.css" rel="stylesheet"/>
+    <!-- Matomo -->
+    <script>
+        var _paq = window._paq = window._paq || [];
+        /* We explicitly disable cookie tracking to avoid privacy issues */
+        _paq.push(['disableCookies']);
+        /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
+        _paq.push(['trackPageView']);
+        _paq.push(['enableLinkTracking']);
+        (function() {
+            var u="https://analytics.apache.org/";
+            _paq.push(['setTrackerUrl', u+'matomo.php']);
+            _paq.push(['setSiteId', '27']);
+            var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
+            g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
+        })();
+    </script>
+    <!-- End Matomo Code -->
 </head>
 <body>
 <!-- header -->
@@ -57,6 +67,21 @@
                         <li class="nav-item">
                             <a class="nav-link" href="download.html">Download</a>
                         </li>
+
+                        <li class="nav-item dropdown">
+                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown4" role="button" data-bs-toggle="dropdown" aria-expanded="false">
+                                Tools
+                            </a>
+                            <ul class="dropdown-menu" aria-labelledby="navbarDropdown4">
+                                <li><a class="dropdown-item" href="providers.html">Graph Systems</a></li>
+                                <li><a class="dropdown-item" href="community.html">Languages and Tools</a></li>
+                                <li><hr class="dropdown-divider"></li>
+                                <li><a class="dropdown-item" href="https://gremlify.com/">Gremlify: Try Gremlin</a></li>
+                                <li><a class="dropdown-item" href="https://tinkerpop.apache.org/gremlint">Gremlint: Lint Gremlin</a></li>
+                                <li><a class="dropdown-item" href="https://www.gremlator.com/">Gremlator: Translate Gremlin</a></li>
+                            </ul>
+                        </li>
+
                         <li class="nav-item dropdown">
                             <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
                                data-bs-toggle="dropdown" aria-expanded="false">
@@ -79,6 +104,7 @@
                             </ul>
 
                         </li>
+
                         <li class="nav-item dropdown">
                             <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown1" role="button"
                                data-bs-toggle="dropdown" aria-expanded="false">
@@ -108,48 +134,31 @@
 
                         </li>
                         <li class="nav-item dropdown">
-                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown3" role="button"
-                               data-bs-toggle="dropdown" aria-expanded="false">
+                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown3" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                                 Community
                             </a>
                             <ul class="dropdown-menu" aria-labelledby="navbarDropdown3">
-                                <li><a class="dropdown-item" href="https://groups.google.com/group/gremlin-users">User
-                                    Mailing List</a></li>
-                                <li><a class="dropdown-item"
-                                       href="https://lists.apache.org/list.html?dev@tinkerpop.apache.org">Developer
-                                    Mailing List</a></li>
-                                <li><a class="dropdown-item" href="https://discord.gg/ndMpKZcBEE" target="_blank"><img
-                                        src="img/discord_logo.png" class="nav-icon">Join us on Discord</a></li>
-                                <li><a class="dropdown-item" href="https://issues.apache.org/jira/browse/TINKERPOP/">Issue
-                                    Tracker</a></li>
-                                <li><a class="dropdown-item"
-                                       href="https://tinkerpop.apache.org/docs/current/dev/developer/#_contributing">Contributing</a>
-                                </li>
-                                <li><a class="dropdown-item" href="providers.html">Data System Support</a></li>
-                                <li><a class="dropdown-item" href="community.html">Languages and Tools</a></li>
-                                <li><a class="dropdown-item"
-                                       href="https://tinkerpop.apache.org/docs/current/dev/provider/#policies">Policies</a>
-                                </li>
-                                <li>
-                                    <hr class="dropdown-divider">
-                                </li>
-                                <li><a class="dropdown-item" href="https://github.com/apache/tinkerpop/"><img
-                                        src="img/github-logo.png" class="nav-icon">GitHub</a></li>
-                                <li><a class="dropdown-item" href="https://twitter.com/apachetinkerpop"><img
-                                        src="img/twitter-logo.png" class="nav-icon">Twitter</a></li>
+                                <li><a class="dropdown-item" href="https://discord.gg/kfebyvDM9H" target="_blank"><img src="img/discord-logo.png" class="nav-icon"/>Discord</a></li>
+                                <li><a class="dropdown-item" href="https://www.answeroverflow.com/c/838910279550238720"><img src="img/answer-overflow-logo.png" class="nav-icon"/>Answer Overflow</a></li>
+                                <li><a class="dropdown-item" href="https://stackoverflow.com/questions/tagged/gremlin"><img src="img/stack-overflow-logo.png" class="nav-icon"/>Stack Overflow</a></li>
+                                <li><a class="dropdown-item" href="https://groups.google.com/group/gremlin-users"><img src="img/mail.png" class="nav-icon"/>User Mailing List</a></li>
+                                <li><a class="dropdown-item" href="https://lists.apache.org/list.html?dev@tinkerpop.apache.org"><img src="img/mail.png" class="nav-icon"/>Developer Mailing List</a></li>
+                                <li><a class="dropdown-item" href="https://issues.apache.org/jira/browse/TINKERPOP/"><img src="img/jira-logo.png" class="nav-icon"/>Issue Tracker</a></li>
+                                <li><a class="dropdown-item" href="https://github.com/apache/tinkerpop/"><img src="img/github-logo.png" class="nav-icon"/>GitHub</a></li>
+                                <li><a class="dropdown-item" href="https://www.twitch.tv/apachetinkerpop"><img src="img/twitch-logo.png" class="nav-icon"/>Twitch</a></li>
+                                <li><a class="dropdown-item" href="https://twitter.com/apachetinkerpop"><img src="img/twitter-logo.png" class="nav-icon"/>Twitter</a></li>
+                                <li><a class="dropdown-item" href="https://www.youtube.com/@apachetinkerpop"><img src="img/youtube-logo.png" class="nav-icon"/>YouTube</a></li>
+                                <li><hr class="dropdown-divider"></li>
+                                <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/dev/developer/#_contributing">Contributing</a></li>
+                                <li><a  class="dropdown-item" href="https://tinkerpop.apache.org/docs/current/dev/provider/#policies">Policies</a></li>
                             </ul>
-
-                        </li>
-
-                        <li class="nav-item">
-                            <a class="nav-link" href="https://tinkerpop.apache.org/gremlint/">Gremlint</a>
                         </li>
                         <li class="nav-item dropdown">
-                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown4" role="button"
+                            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown5" role="button"
                                data-bs-toggle="dropdown" aria-expanded="false">
                                 Apache Software
                             </a>
-                            <ul class="dropdown-menu" aria-labelledby="navbarDropdown4">
+                            <ul class="dropdown-menu" aria-labelledby="navbarDropdown5">
                                 <li><a class="dropdown-item" href="https://www.apache.org/">Apache Homepage</a></li>
                                 <li><a class="dropdown-item" href="https://www.apache.org/licenses/">License</a></li>
                                 <li><a class="dropdown-item"
@@ -522,9 +531,9 @@
         <div class="row d-flex justify-content-center">
             <div class="col-md-8 col-lg-6">
                 <div class="ju-box">
-                    <h2 class="ft-40 text-blue bold">Join Us on</h2>
-                    <p class="bold">Join us on our Discord Chat</p>
-                    <a href="https://discord.gg/ndMpKZcBEE"><img src="img/tpvewx.png" class="img-fluid mt-3" alt="img"></a>
+                    <h2 class="ft-40 text-blue bold">Join Us</h2>
+                    <p class="bold">Join us on our Discord Server</p>
+                    <a href="https://discord.gg/kfebyvDM9H"><img src="img/tpvewx.png" class="img-fluid mt-3" alt="img"></a>
                 </div>
             </div>
         </div>
@@ -538,15 +547,13 @@
             <div class="row">
                 <div class="col-md-4">
                     <div class="bold ft-25">Apache TinkerPop™</div>
-                    <p class="mt-2 mb-4">Apache TinkerPop™ is a graph computing framework for both graph databases
-                        (OLTP) and graph analytic systems (OLAP).</p>
+                    <p class="mt-2 mb-4">Apache TinkerPop™ is a graph computing framework for both graph databases (OLTP) and graph analytic systems (OLAP).</p>
                     <ul class="list-unstyled list-inline hover-op-low">
-                        <li class="list-inline-item"><a href="https://discord.gg/ndMpKZcBEE"><img
-                                src="img/social/discord.svg" class="img-fluid" alt="img"></a></li>
-                        <li class="list-inline-item"><a href="https://twitter.com/apachetinkerpop"><img
-                                src="img/social/twitter-square.svg" class="img-fluid" alt="img"></a></li>
-                        <li class="list-inline-item"><a href="https://github.com/apache/tinkerpop"><img
-                                src="img/social/github-box.svg" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://discord.gg/kfebyvDM9H"><img src="img/social/discord.svg" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://github.com/apache/tinkerpop"><img src="img/social/github-box.svg" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://www.twitch.tv/apachetinkerpop"><img src="img/social/twitch.png" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://twitter.com/apachetinkerpop"><img src="img/social/twitter-square.svg" class="img-fluid" alt="img"></a></li>
+                        <li class="list-inline-item"><a href="https://www.youtube.com/@apachetinkerpop"><img src="img/social/youtube.png" class="img-fluid" alt="img"></a></li>
                     </ul>
                 </div>
                 <div class="col-md-4 ft-links">
@@ -557,6 +564,7 @@
                                 <li><a href="index.html">Home</a></li>
                                 <li><a href="download.html">Downloads</a></li>
                                 <li><a href="https://tinkerpop.apache.org/docs/current">Documentation</a></li>
+                                <li><a href="https://privacy.apache.org/policies/privacy-policy-public.html" target="_blank">Privacy Policy</a></li>
                             </ul>
                         </div>
                         <div class="col-lg-6">
@@ -581,7 +589,7 @@
         <div class="container">
             <div class="row">
                 <div class="col-12">
-                    Copyright © 2015-2022 The Apache Software Foundation
+                    Copyright © 2015-2023 The Apache Software Foundation
                 </div>
             </div>
         </div>
@@ -589,9 +597,7 @@
 </footer>
 <script src="js/jquery-1.11.1.js"></script>
 <script src="js/bootstrap.bundle.min.js"></script>
-<script src="https://cdnjs.cloudflare.com/ajax/libs/wow/1.1.2/wow.min.js"
-        integrity="sha512-Eak/29OTpb36LLo2r47IpVzPBLXnAMPAVypbSZiZ4Qkf8p/7S/XRG5xp7OKWPPYfJT6metI+IORkR5G8F900+g=="
-        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
+<script src="js/wow.min.js"></script>
 <script src="js/my.js"></script>
 </body>
 </html>
diff --git a/docs/src/dev/developer/administration.asciidoc b/docs/src/dev/developer/administration.asciidoc
index 53be99a..d8b79f6 100644
--- a/docs/src/dev/developer/administration.asciidoc
+++ b/docs/src/dev/developer/administration.asciidoc
@@ -121,9 +121,10 @@
 [include the link to the vote result thread from private]
 ----
 
-If the candidate does not (yet) have an Apache account, then please note that fact in the notification email. Provide
-the board 72 hours to respond with objection before extending the invite to the new PMC member. Once that time has
-elapsed, the invite may be sent to the new PMC member. The following template may be used for the invitation (be sure
+If the candidate does not (yet) have an Apache account, then please note that fact in the notification email.
+It is important to verify that this NOTICE was actually included in the
+link:https://mail-search.apache.org/members/private-arch/board[board archive] to ensure that is has been delivered to the board.
+After verifying this, the invite may be sent to the new PMC member. The following template may be used for the invitation (be sure
 to copy private@ when sending the email):
 
 [source,text]
@@ -146,41 +147,12 @@
 == Board Reports
 
 The PMC Chair is responsible for submitting a link:http://www.apache.org/foundation/board/reporting[report to the board]
-on a quarterly basis. TinkerPop reports on the following months: January, April, July, October. The report has the
-following format:
-
-[source,text]
-----
-## Description:
- Apache TinkerPop is a graph computing framework for both graph databases
- (OLTP) and graph analytic systems (OLAP).
-
-## Activity:
- <discuss general project health, project direction, community growth/activity, etc.>
-
-## Issues:
- There are no issues requiring board attention at this time.
-
-## Releases:
- - x.y.z (<month> <day>, <year>)
- - x.y.z (<month> <day>, <year>)
-
-## PMC/Committer:
-
- - Last PMC addition was <name> - <month> <year>
- - Last committer addition was <name> - <month> <year>
-
-## Links
-
-[1] <hyperlink to external reference, if a reference was made in the report>
-----
+on a quarterly basis. TinkerPop reports on the following months: January, April, July, October.
 
 A draft of the report should be sent to the TinkerPop developer mailing list for review at least three days prior to
-submitting to the board. The final report should be sent in plain-text format to `board@apache.org` and should be
-committed to the appropriate meeting agenda in SVN at:
-
-[source,text]
-https://svn.apache.org/repos/private/foundation/board
+submitting to the board. The final report can be submitted via link:https://whimsy.apache.org/board/agenda/[Whimsy] or
+via the link:https://reporter.apache.org[Apache Reporter Service] which already provides a template for the report and
+explains the different sections.
 
 [[contributor-listing]]
 == Contributor Listing
diff --git a/docs/src/dev/developer/development-environment.asciidoc b/docs/src/dev/developer/development-environment.asciidoc
index 6f85601..831da1f 100644
--- a/docs/src/dev/developer/development-environment.asciidoc
+++ b/docs/src/dev/developer/development-environment.asciidoc
@@ -28,7 +28,9 @@
 
 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
+cross-compilation happens automatically as part of the build). Starting with 3.7.0, you can also build with
+link:https://openjdk.org/projects/jdk/17/[Java 17]. Note, however, that there are some issues with deep reflection
+so there are `--add-opens` JVM options included in the pom files to enable this to work. Maven (requiring a minimum of
 link:https://maven.apache.org/download.cgi[Maven 3.5.3+]) is used as the common build system, which even
 controls the builds of non-JVM link:https://tinkerpop.apache.org/docs/x.y.z/reference/#gremlin-drivers-variants[GLVs]
 such as `gremlin-python`. Java and Maven are described as a "minimum" for a development environment, because they
@@ -215,6 +217,15 @@
 in the `.m2` (`~/.m2/`) and in the `grapes` (`~/.groovy/grapes/`) cache. E.g., if the error is about
 `asm#asm;3.2!asm.jar`, then remove the `asm/asm` sub directory in both directories.
 
+NOTE: Unexpected failures with OLAP often point to a jar conflict that arises in scenarios where Hadoop or Spark
+dependencies (or other dependencies for that matter) are modified and conflict. It is not picked up by the enforcer
+plugin because the inconsistency arises through plugin installation in Gremlin Console at document generation time.
+Making adjustments to the various paths by way of the `<manifestEntries>` on the jar given the functionality provided
+by the `DependencyGrabber` class which allows you to manipulate (typically deleting conflicting files from `/lib` and
+`/plugin`) plugin loading will usually resolve it, though it could also be a more general environmental problem with
+Spark or Hadoop. The easiest way to see the error is to simply run the examples in the Gremlin Console which more
+plainly displays the error than the failure of the documentation generation process.
+
 To generate the web site locally, there is no need for any of the above infrastructure. Site generation is a simple
 shell script:
 
diff --git a/docs/src/dev/developer/for-committers.asciidoc b/docs/src/dev/developer/for-committers.asciidoc
index fbaf0e2..16e11e2 100644
--- a/docs/src/dev/developer/for-committers.asciidoc
+++ b/docs/src/dev/developer/for-committers.asciidoc
@@ -587,6 +587,28 @@
 Tag filters can be applied to Intellij at execution time by adding a system properties of
 `-Dcucumber.filter.tags=<step-filter>`.
 
+[[gremlin-socket-server-tests]]
+=== Gremlin Socket Server Tests
+`gremlin-socket-server` is an included test server for driver tests which require predefined server
+behavior. Typically, this is to test scenarios such as the server closing the connection or returning
+an error code but other response behavior can be added as needed for tests.
+
+Gremlin socket server uses the request id of incoming messages to determine how to respond.
+Request ids are defined in `gremlin-tools/gremlin-socket-server/conf/*.yaml`. The server side
+behavior for each request id is implemented in `TestWSGremlinInitializer`.
+
+To add new server side behavior, define a new request id in the config yaml, then add a corresponding
+field in `SocketServerSettings`. In `TestWSGremlinInitializer`, add a new block to the if else chain in the
+decode method which matches the request id. Define all server behavior and responses in this block.
+
+To write the driver test, send a request message to the gremlin socket server port as if it were a normal
+gremlin server. Override the request id on the request with one defined in the config yaml and gremlin
+socket server will respond according to the defined behavior.
+
+Ensure that the socket server is running during driver tests. By default, a docker image for
+`gremlin-socket-server` is built during `mvn install`. The simplest way to use the socket server during
+driver tests is to run a gremlin socket server container during the integration phase of driver tests.
+
 == Developing Benchmarks
 
 Benchmarks are a useful tool to track performance between TinkerPop versions and also as tools to aid development
diff --git a/docs/src/dev/developer/index.asciidoc b/docs/src/dev/developer/index.asciidoc
index 6031142..3af4d0b 100644
--- a/docs/src/dev/developer/index.asciidoc
+++ b/docs/src/dev/developer/index.asciidoc
@@ -14,12 +14,15 @@
 See the License for the specific language governing permissions and
 limitations under the License.
 ////
+
+:docinfo: shared
+:docinfodir: ../../
+:toc-position: left
+
 image::apache-tinkerpop-logo.png[width=500,link="https://tinkerpop.apache.org"]
 
 *x.y.z*
 
-:toc-position: left
-
 = Developer Documentation
 
 This document contains information for TinkerPop developers, contributors, and community members. It focuses on
diff --git a/docs/src/dev/future/index.asciidoc b/docs/src/dev/future/index.asciidoc
index 76a4c5d..f849877 100644
--- a/docs/src/dev/future/index.asciidoc
+++ b/docs/src/dev/future/index.asciidoc
@@ -1,5 +1,3 @@
-= TinkerPop Future
-
 ////
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements.  See the NOTICE file distributed with
@@ -16,9 +14,16 @@
 See the License for the specific language governing permissions and
 limitations under the License.
 ////
+
+:docinfo: shared
+:docinfodir: ../../
+:toc-position: left
+
 image::apache-tinkerpop-logo.png[width=500,link="https://tinkerpop.apache.org"]
 
-:toc-position: left
+*x.y.z*
+
+= TinkerPop Future
 
 This document offers a rough view at what features can be expected from future releases and catalogs proposals for
 changes that might be better written and understood in a document form as opposed to a dev list post.
@@ -42,14 +47,14 @@
 are removed with new items taking their place as they are planned. The release line is removed from the roadmap
 completely when it is no longer maintained.
 
-== 3.7.x - Target 22Q4
+== 3.7.x - Target 2023H1
 
-Development has not yet started on the 3.7.x release line with a targeted release date for the initial release of the
-line of 22H2.
+The development of the 3.7.x release line is currently under way with a target release date for the initial release of
+the line of 23H1.
 
 * Add support for traversals as parameters for `V()`, `is()`, and `has()` (includes `Traversal` arguments to `P`)
 * Geospatial support for TinkerPop (link:++https://lists.apache.org/list?dev@tinkerpop.apache.org:2021-7:DISCUSS%20geo-spatial++[DISCUSS Thread])
-* Add mid-traversal `E()` support
+* Add mid-traversal `E()` support (link:https://issues.apache.org/jira/browse/TINKERPOP-2798[TINKERPOP-2798])
 * Allow properties on elements (as opposed to just references) for remote traversals
 * Add subgraph/tree structure in all GLVs
 * List functions (`concat()`/etc.)
@@ -91,6 +96,8 @@
 |=========================================================
 |Proposal |Description |Targets |Resolved
 |link:https://github.com/apache/tinkerpop/blob/master/docs/src/dev/future/proposal-equality-1.asciidoc[Proposal 1] |Equality, Equivalence, Comparability and Orderability Semantics - Documents existing Gremlin semantics along with clarifications for ambiguous behaviors and recommendations for consistency. |3.6.0 |N
+|link:https://github.com/apache/tinkerpop/blob/master/docs/src/dev/future/proposal-arrow-flight-2[Proposal 2] |Gremlin Arrow Flight. |4.0.0 |N
+|link:https://github.com/apache/tinkerpop/blob/master/docs/src/dev/future/proposal-3-remove-closures[Proposal 3] |Removing the Need for Closures/Lambda in Gremlin |3.7.0 |N
 |=========================================================
 
 = Appendix
diff --git a/docs/src/dev/future/proposal-3-remove-closures.asciidoc b/docs/src/dev/future/proposal-3-remove-closures.asciidoc
new file mode 100644
index 0000000..3ab694e
--- /dev/null
+++ b/docs/src/dev/future/proposal-3-remove-closures.asciidoc
@@ -0,0 +1,1513 @@
+////
+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.
+////
+== Proposal 3 - Removing the Need for Closures/Lambda in Gremlin
+
+=== Status
+
+This proposal has been accepted through a post to the TinkerPop Dev List and is ready to begin implementaion.
+
+=== Motivation
+
+There are a number of useful operations that Gremlin users often wish to
+perform that are not provided today in the form of traversal steps or
+predicates (P/TextP). For historical reasons these functions were
+omitted and users were able to accomplish these tasks by specifying
+anonymous code blocks or “closures” to perform these tasks. For example,
+below is an example of how you can achieve a case-insensitive search for
+any cities that contain “Miami”.
+
+....
+g.V().hasLabel('city').
+    has('name',filter{it.get().toLowerCase().contains('Miami'.toLowerCase())})
+....
+
+While this is just one example of how closures are used, they are a
+powerful fallback mechanism in Gremlin to handle use cases where there
+is no functionality within the Gremlin language to meet the
+requirements. However, for a variety of reasons such as security and
+performance, many/most remote providers of TinkerPop do not allow users
+to execute closures as part of a query. This leaves users with a
+problem, as the mechanism provided to solve these sorts of use cases is
+not allowed. Examples of some commonly requested functionality that
+cannot be accomplished without the use of closures would be:
+
+[cols=",,",options="header",]
+|===
+|String Functions |List Functions |Date Functions
+|asString |reverse |dateAdd
+|concat |remove |dateDiff
+|length |indexOf |asDate
+|split |product |
+|substring |all |
+|rTrim |any |
+|lTrim |none |
+|trim |concat |
+|replace |length |
+|reverse |intersect |
+|toUpper |difference |
+|toLower |union |
+|===
+
+=== Considerations
+
+* Adding full support for traversals as parameters to predicates would
+simplify the syntax of these examples. However, this is a known issue
+with Gremlin and none of the proposed options below are blocked by it,
+nor do they exacerbated this issue any further. As such, the
+ramifications of that change are not covered by this proposal.
+
+=== Proposed Options and Recommendation
+
+==== Option 1 (Recommended)
+
+Create a new Gremlin step for each of the desired functions a user is
+looking to perform. Each step encapsulates a set of functionality that
+customers are looking to achieve. While certain steps may be reused
+across input types (e.g. `reverse()` for both list and string inputs)
+the behaviors of each step is well-defined for a given input type.
+
+*Example*: Find me all `city` nodes with a `name` starting with `miami`,
+ignoring case?
+`g.V().hasLabel('city').where(values('name').toLower(), eq('miami'))`
+
+===== Pros:
+
+* Most similar to current Gremlin patterns for adding steps
+* Feel the most like Gremlin when writing the
+
+===== Cons:
+
+* Would result in a potentially large number of steps being added to the
+language, hindering discoverability
+* Adds complexity to creating and maintaining all the current GLVs due
+to the number of new steps.
+
+==== Option 2
+
+Create a single Gremlin step that take the operation as a parameter and
+uses that parameter to mutate the behavior to achieve the desired
+functionality.
+
+*Example*: : Find me all `city` nodes with a `name` starting with
+`miami`, ignoring case?
+`g.V().hasLabel('city').where(F.apply(Func.toLower, values('name')), eq('miami'))`
+
+===== Pros:
+
+* Single step simplifies adding new operations across GLVs
+
+===== Cons:
+
+* Introduces a novel concept, a function, to the Gremlin language
+* No set signature for `F.apply` as it will differ per operation
+
+==== Option 3
+
+Create a new type of predicate in Gremlin that specifies the operation
+and returns the correct output. This would be a new paradigm within
+Gremlin, as it extends predicates to return non-boolean results.
+
+*Example*:: Find me all `city` nodes with a `name` starting with
+`miami`, ignoring case?
+`g.V().hasLabel('city').where(SP.toLower(values('name')).is('miami'))`
+
+===== Pros:
+
+* Single predicate simplifies adding new operations as they are now a
+token and not a new step that needs to be propagated across all the GLVs
+
+===== Cons:
+
+* New paradigm in Gremlin that further blurs the line between predicates
+and steps
+* Signature differs for each predicate operation
+* Signatures of common steps needs to change to include options like
+`where(Predicate)`
+
+=== Proposed Syntax
+
+<<string-function-syntax>>
+
+<<list-function-syntax>>
+
+<<date-function-syntax>>
+
+=== Examples
+
+==== String Examples
+
+===== String Example 1 (SE1)
+
+I want to find the offices, by name, where the name does not have a "-"
+as the third character of the string
+(https://stackoverflow.com/questions/56115935/gremlin-is-there-a-way-to-find-the-character-based-on-the-index-of-a-string[here])
+
+`g.V().hasLabel('office').where(__.values('name').substr(2, 1)).is(neq('-'))) `
+
+===== String Example 2 (SE2)
+
+I would like to trim out the "Mbit/s" from the string
+(https://stackoverflow.com/questions/45365726/im-unable-to-substring-values-that-i-get-by-running-a-gremlin-query-ive-been[here])
+
+`g.V('Service').has('serviceId','ETHA12819844').out('AssociatedToService').`
+`value("bandwidth").replace("Mbit/s", "")`
+
+===== String Example 3 (SE3)
+
+I am trying to add a new vertex which should be labeled like an existing
+vertex but with some prefix attached
+(https://stackoverflow.com/questions/61106927/concatenate-gremlin-graphtraversal-result-with-string[here])
+
+....
+`g.V(3).as('a').addV(constant("").concat("prefix_", select('a').label())`
+....
+
+===== String Example 4 (SE4)
+
+Find all products that start with the same case-insensitive prefix. +
+e.g. Given the following products:
+
+[cols=",",options="header",]
+|===
+|id |product_name
+|1 |PROD-123
+|2 |PROD-234
+|3 |TEST-1234
+|4 |GAMMA-1234
+|5 |PR-123
+|===
+
+We should return:
+
+[cols=",",options="header",]
+|===
+|id |product_name
+|1 |PROD-123
+|2 |PROD-234
+|===
+
+....
+g.V().hasLabel('Product').has('product_name').as('product1').
+  V().hasLabel('Product').has('product_name'`).`
+  where(__.is(select('product1').toLower())`.values('product_name').substring(0, 5)).
+  select('product1')
+....
+
+===== String Example 5 (SE5)
+
+Perform case-insensitive search
+
+....
+g.V().hasLabel('Product').where(values('product_name').toLower(), eq('foo'))
+....
+
+===== String Example 6 (SE6)
+
+Applying functions to returning values, in this case return the `age`
+and a lower cased version of `name`
+
+`g.V().hasLabel('person').valueMap('age', 'name').by().by(toLower())`
+
+===== String Example 7 (SE7)
+
+Concatenating values on the return, in this case return a concatenated
+name
+
+`g.V().hasLabel('person').project('age', 'name').` `by('age').`
+`by(values('first_name').concat(" ").concat(values('last_name'))`
+
+==== List Examples
+
+===== List Example 1 (LE1)
+
+Given a list of people, return the list of `age`s if everyone’s `age` >
+18
+
+`g.V().hasLabel('person').values('age').fold().where(all(gt(18)))`
+
+===== List Example 2 (LE2)
+
+Given a set of vertices, return the list of vertices if anyone’s `age` >
+18
+
+`g.V([1,2,3,4]).fold().where(any(values('age').is(gt(18))))`
+
+===== List Example 3 (LE3)
+
+Given a list, find the index of the first occurrence of `Dave`
+
+`g.V().hasLabel('person').fold().indexOf(has('name', 'Dave'))` `==> 12`
+
+`g.inject(['Dave', 'Kelvin', 'Stephen']).indexOf(constant('Dave'))`
+`==> 0`
+
+===== List Example 4 (LE4)
+
+Given a list of people, remove any person with a name of `Dave`
+
+`g.V().hasLabel('person').fold().remove(has('name', 'Dave'))`
+`==> [‘Kelvin’, ‘Stephen’]`
+
+`g.inject(['Dave', 'Kelvin', 'Stephen']).remove(constant('Dave'))`
+`==> [‘Kelvin’, ‘Stephen’]`
+
+`g.inject(['Dave', 'Kelvin', 'Stephen']).remove(constant(['Dave', 'Stephen'))`
+`==> ['Kelvin']`
+
+==== Date Examples
+
+===== Date Example 1 (DE1)
+
+Given a transaction, find me all other transactions within 7 days prior
+
+`g.V('transaction1').values('date').dateAdd(DT.Days, -7).as('purchase_date').V().hasLabel('transaction').where(gt('purchase_date')).by('date').by()`
+
+===== Date Example 2 (DE2)
+
+Given two transactions, find me the difference in the dates
+
+`g.V('transaction1').values('date').dateDiff(DT.Days, V('transaction2').values('date').asDate())`
+
+===== Date Example 3 (DE3)
+
+Given a static value, return me the value as a date
+
+`g.inject('1900-01-01').asDate()`
+
+===== Date Example 4 (DE4)
+
+Find the difference between a transaction and the first of the year
+
+`g.V('transaction1').values('date').dateDiff(DT.Days, inject(datetime('2023-01-01'))`
+
+
+
+== String Manipulation functions in TinkerPop [[string-function-syntax]]
+
+One of the common gaps that user's find when using Gremlin is that there
+is a lack of string manipulation capabilities within the language
+itself. This requires that users use closures to handle many common
+string manipulation options that users want to do on data in the graph.
+This is a problem for many users as many of the providers prevent the
+use of arbitrary closures due to the security risks so for these users
+there is no way to manipulate strings directly.
+
+=== Proposal
+
+The proposal here is to add a set of steps to handle common string
+manipulation requests from users, the details for each are discussed
+below:
+
+* <<asString, asString()>>
+* <<concat, concat()>>
+* <<length, length()>>
+* <<split, split()>>
+* <<substring, substring()>>
+* <<rTrim, rTrim()>>
+* <<lTrim, lTrim()>>
+* <<trim, trim()>>
+* <<replace, replace()>>
+* <<reverse, reverse()>>
+* <<toUpper, toUpper()>>
+* <<toLower, toLower()>>
+
+=== Gremlin Language Variant Function Names
+
+[cols=",,,,,",options="header",]
+|===
+|Groovy |Java |Python |JavaScript |.NET |Go
+|asString() |asString() |as_string() |asString() |AsString() |AsString()
+
+|concat() |concat() |concat() |concat() |Concat() |Concat()
+
+|length() |length() |length() |length() |Length() |Length()
+
+|split() |split() |split() |split() |Split() |Split()
+
+|substring() |substring() |substring() |substring() |Substring()
+|Substring()
+
+|rTrim() |rTrim() |rtrim() |rTrim() |RTrim() |RTrim()
+
+|lTrim() |lTrim() |ltrim() |lTrim() |LTrim() |LTrim()
+
+|trim() |trim() |trim() |trim() |Trim() |Trim()
+
+|replace() |replace() |replace() |replace() |Replace() |Replace()
+
+|reverse() |reverse() |reverse() |reverse() |Reverse() |Reverse()
+
+|toUpper() |toUpper() |to_upper() |toUpper() |ToUpper() |ToUpper()
+
+|toLower() |toLower() |to_lower() |toLower() |ToLower() |ToLower()
+|===
+
+'''''
+
+== Function Definitions
+
+=== `asString()` [[asString]]
+
+Returns the value of the incoming traverser as a string
+
+==== Signature(s)
+
+`asString()`
+
+`asString(Scope)`
+
+==== Parameters
+
+* Scope - Scope Enum
+
+==== Allowed incoming traverser types
+
+Any data type allowed by TinkerPop
+
+==== Expected Output
+
+A String value representing the string value of the traverser being
+passed in as shown below:
+
+[cols=",,",options="header",]
+|===
+|Incoming Datatype |Example Query |Example Output
+|Integer |`g.inject(29).asString()` |29
+
+|Float |`g.inject(29.0).asString()` |29.0
+
+|String |`g.inject('foo').asString()` |foo
+
+|UUID |`g.inject(UUID.randomUUID()).asString()`
+|47557eed-04e7-4aa4-89eb-9689d26fe94a
+
+|Map
+|`g.inject([["id": 1], ["id": 2, "something":"anything"]]).asString()`
+|[[id:1], [id:2, something:anything]]
+
+|Date |`g.inject(datetime()).asString()` |Sun Nov 04 00:00:00 UTC 2018
+
+|List |`g.inject([1,2,3]).asString()` |[1, 2, 3]
+
+|List (Local Scope) |`g.inject([1,2,3]).asString(local)` |["1", "2",
+"3"]
+
+|Vertex |`g.V(1).asString()` |v[1]
+
+|Edge |`g.E(7).asString()` |e[7][1-knows->2]
+
+|Property |`g.V(1).properties('age').asString()` |vp[age->29]
+
+|null |`g.V().group().by('foo').select(keys).asString()` |null
+|===
+
+'''''
+
+=== `concat()` [[concat]]
+
+Concatenates one or more strings together
+
+==== Signature(s)
+
+`concat(String...)`
+
+`concat(Traversal)`
+
+`concat(Scope, String...)`
+
+`concat(Scope, Traversal)`
+
+==== Parameters
+
+* String... - One or more String values to concatenate to the input
+string
+* Traversal - A traversal value to concatenate
+* Scope - Scope Enum
+
+==== Allowed incoming traverser types
+
+String data types or array, if local scope is used. If a non-string
+traverser, or the list containing non-string values, is passed in then
+an `IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+A String value representing the concatenation of all the
+
+....
+g.inject('this').concat('is', 'a', 'test')
+==>thisisatest
+g.V(1).values('first_name').concat(' ').concat(V(1).values('last_name')
+==>John Doe
+g.inject(['this', 'is', 'a', 'test']).concat(local)
+==>thisisatest
+g.inject(['John', ' ']).concat(local, V(1).values('last_name')
+==>John Doe
+....
+
+*Note* `concat()` may also be extended to handle concatenating list
+values together but that is out of scope for this change.
+
+'''''
+
+=== `length()` [[length]]
+
+Returns the length of the input string
+
+==== Signature(s)
+
+`length()`
+
+`length(Scope)`
+
+==== Parameters
+
+* Scope - Scope Enum
+
+==== Allowed incoming traverser types
+
+String data types or array, if local scope is used. If a non-string
+traverser, or the list containing non-string values, is passed in then
+an `IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+A Long value representing the number of items in an array or the number
+of characters in a string
+
+....
+g.inject('this').length()
+==>4
+g.inject('this').length(local)
+==>4
+....
+
+*Note*:While this is similar to `count(local)` they are not the same.
+`count(local)` treats the input by calculating the count of the items
+stored within the traversal. `length()` treats the input as an array and
+provides the length of that array.
+
+[cols=",,,",options="header",]
+|===
+|Input Datatype |Example traversal |count(local) |length()
+|Integer |`g.inject(29)` |1 |IllegalArgumentException
+
+|Float |`g.inject(29.0)` |1 |IllegalArgumentException
+
+|String |`g.inject('foo')` |1 |3
+
+|UUID |`g.inject(UUID.randomUUID())` |1 |IllegalArgumentException
+
+|Map |`g.inject(["id": 2, "something":"anything"]])` |1
+|IllegalArgumentException
+
+|Date |`g.inject(datetime())` |1 |IllegalArgumentException
+
+|List |`g.inject([1,2,3])` |3 |3
+
+|Vertex |`g.V(1)` |1 |IllegalArgumentException
+
+|Edge |`g.E(7)` |1 |IllegalArgumentException
+
+|Property |`g.V(1).properties('age')` |1 |IllegalArgumentException
+
+|null |`g.V().group().by('foo').select(keys)` |0
+|IllegalArgumentException
+|===
+
+'''''
+
+=== `split()` [[split]]
+
+Returns a list of strings created by splitting the input string around
+the matches of the given delimiter.
+
+==== Signature(s)
+
+`split(String)`
+
+`split(Scope, String)`
+
+==== Parameters
+
+* String - The delimiter character(s) to split the input string* *
+
+==== Allowed inputs
+
+String data types or array, if local scope is used. If a non-string
+traverser, or the list containing non-string values, is passed in then
+an `IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+An array of strings split around the delimiter character(s)
+
+....
+g.inject('this').split('h')
+==>[t, is]
+g.inject('one,two').split(',')
+==>[one, two]
+g.inject('axxb').split('x')
+==>[a, b]
+g.inject('axybxc').split('xy')
+==>[a, bxc]
+g.inject(['this', 'that']).split('h')
+==>[[t, is], [t, at]]
+....
+
+'''''
+
+=== `substring()` [[substring]]
+
+returns a substring of the original string with the length specified,
+uses a 0-based start
+
+==== Signature(s)
+
+`substring(Long, Long)`
+
+`substring(Long)`
+
+`substring(Scope, Long, Long)`
+
+`substring(Scope, Long)`
+
+==== Parameters
+
+* Long - The start index, 0 based. If the value is negative then the
+start location will be the end of the string and it will go the
+specified number of characters from the end of the string.
+* Long - The number of characters to return. Optional - if not provided
+then all remaining characters will be returned
+* Scope - Scope Enum
+
+==== Allowed incoming traverser types
+
+String data types or array, if local scope is used. If a non-string
+traverser, or the list containing non-string values, is passed in then
+an `IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+A String value containing the number of characters specified beginning
+at the start location. If the start location plus the length specified
+is greater than or equal to the input length, the result will contain
+the entire string.
+
+....
+g.inject('this').substring(0, 1)
+==>t
+g.inject('this').substring(2)
+==>is
+g.inject('this').substring(2, 5)
+==>is
+g.inject('this').substring(-1)
+==>s
+g.inject(['this', 'is', 'a', 'test']).substring(local, 2)
+==>[is, '' ,'' , 'st']
+....
+
+'''''
+
+=== `rTrim()` [[rTrim]]
+
+Returns a string with trailing whitespace removed
+
+*Note*: Whitespace characters are defined as space/tab/line feed/line
+tabulation/form feed/carriage return.
+
+==== Signature(s)
+
+`rTrim()`
+
+`rTrim(Scope)`
+
+==== Parameters
+
+* Scope - Scope Enum
+
+==== Allowed incoming traverser types
+
+String data types or array, if local scope is used. If a non-string
+traverser, or the list containing non-string values, is passed in then
+an `IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+A string value with trailing whitespace removed
+
+....
+g.inject('this ').rTrim()
+==>this
+g.inject(['this ', 'that ']).rTrim(local)
+==>[this, that]
+....
+
+'''''
+
+=== `lTrim()` [[lTrim]]
+
+Returns a string with leading whitespace removed
+
+*Note*: Whitespace characters are defined as space/tab/line feed/line
+tabulation/form feed/carriage return.
+
+==== Signature(s)
+
+`lTrim()`
+
+`lTrim(Scope)`
+
+==== Parameters
+
+* Scope - Scope Enum
+
+==== Allowed incoming traverser types
+
+String data types or array, if local scope is used. If a non-string
+traverser, or the list containing non-string values, is passed in then
+an `IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+A string value with leading whitespace removed
+
+....
+g.inject(' this').lTrim()
+==>this
+g.inject([' this', ' that']).lTrim(local)
+==>[this, that]
+....
+
+'''''
+
+=== `trim()` [[trim]]
+
+Returns a string with leading and trailing whitespace removed
+
+*Note*: Whitespace characters are defined as space/tab/line feed/line
+tabulation/form feed/carriage return.
+
+==== Signature(s)
+
+`trim()`
+
+`trim(Scope)`
+
+==== Parameters
+
+* Scope - Scope Enum
+
+==== Allowed incoming traverser types
+
+String data types or array, if local scope is used. If a non-string
+traverser, or the list containing non-string values, is passed in then
+an `IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+A string value with leading and trailing whitespace removed
+
+....
+g.inject(' this ').trim()
+==>this
+g.inject([' this ', ' that ']).trim()
+==>[this, that]
+....
+
+'''''
+
+=== `replace()` [[replace]]
+
+Returns a string with the specified characters in the original string
+replaced with the new characters
+
+==== Signature(s)
+
+`replace(String, String)`
+
+`replace(Scope, String, String)`
+
+==== Parameters
+
+* String - The character(s) to be replaced
+* String - The character(s) to replace with
+* Scope - Scope Enum
+
+==== Allowed incoming traverser types
+
+String data types or array, if local scope is used. If a non-string
+traverser, or the list containing non-string values, is passed in then
+an `IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+A string
+
+....
+g.inject('this').replace('t', 'x)
+==>xhis
+g.inject('this').replace('x', 't')
+==>this
+g.inject('this').replace('is', 'was')
+==>thwas
+g.inject(['this', 'that']).replace('th', 'was')
+==>[wasis, wasat]
+....
+
+'''''
+
+=== `reverse()` [[reverse]]
+
+Reverses the current string
+
+==== Signature(s)
+
+`reverse()`
+
+`reverse(Scope)`
+
+==== Parameters
+
+* Scope - Scope Enum
+
+==== Allowed incoming traverser types
+
+String data types or array, if local scope is used. If a non-string
+traverser, or the list containing non-string values, is passed in then
+an `IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+A String value representing the reversed version of the incoming string
+
+....
+g.inject('this').reverse()
+==>siht
+g.inject(['this', 'that']).reverse(local)
+==>[siht, taht]
+....
+
+*Note* `reverse()` may also be extended to handle concatenating list
+values together but that is out of scope for this change.
+
+'''''
+
+=== `toUpper()` [[toUpper]]
+
+Returns an upper case string representation.
+
+*Note*: All case conversions will be done via the mappings specified for
+Unicode (https://www.unicode.org/reports/tr44/#Casemapping[found here])
+
+==== Signature(s)
+
+`toUpper()`
+
+`toUpper(Scope)`
+
+==== Parameters
+
+* Scope - Scope Enum
+
+==== Allowed incoming traverser types
+
+String data types or array, if local scope is used. If a non-string
+traverser, or the list containing non-string values, is passed in then
+an `IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+A string
+
+....
+g.inject('this').toUpper()
+==>THIS
+g.inject(['this', 'that']).toUpper()
+==>[THIS, THAT]
+....
+
+'''''
+
+=== `toLower()` [[toLower]]
+
+Returns an lower case string representation
+
+*Note*: All case conversions will be done via the mappings specified for
+Unicode (https://www.unicode.org/reports/tr44/#Casemapping[found here])
+
+==== Signature(s)
+
+`toLower()`
+
+`toLower(Scope)`
+
+==== Parameters
+
+* Scope - Scope Enum
+
+==== Allowed incoming traverser types
+
+String data types or array, if local scope is used. If a non-string
+traverser, or the list containing non-string values, is passed in then
+an `IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+A string
+
+....
+g.inject('THIS').toLower()
+==>this
+g.inject(['THIS', 'THAT']).toLower()
+==>[this, that]
+....
+
+
+== List Manipulation functions in TinkerPop [[list-function-syntax]]
+
+One of the common gaps that user's find when using Gremlin is that there
+is a lack of list manipulation capabilities within the language itself.
+This requires that users use closures to handle many common manipulation
+options that users want to do on data in the graph. This is a problem
+for many users as many of the providers prevent the use of arbitrary
+closures due to the security risks so for these users there is no way to
+manipulate strings directly.
+
+=== Proposal
+
+The proposal here is to add a set of steps to handle common list
+manipulation requests from users, the details for each are discussed
+below:
+
+* <<length_list, length()>>
+* <<reverse_list, reverse()>>
+* <<remove_list, remove()>>
+* <<indexOf_list, indexOf()>>
+* <<product_list, product()>>
+* <<all_list, all()>>
+* <<any_list, any()>>
+* <<none_list, none()>>
+* <<concat_list, concat()>>
+* <<intersect_list, intersect()>>
+* <<union_list, union()>>
+* <<difference_list, difference()>>
+* <<disjunct_list, disjunct()>>
+
+=== Gremlin Language Variant Function Names
+
+[cols=",,,,,",options="header",]
+|===
+|Groovy |Java |Python |JavaScript |.NET |Go
+|length() |length() |length() |length() |Length() |Length()
+
+|reverse() |reverse() |reverse() |reverse() |Reverse() |Reverse()
+
+|remove() |remove() |remove() |remove() |Remove() |Remove()
+
+|indexOf() |indexOf() |index_of() |indexOf() |IndexOf() |IndexOf()
+
+|product() |product() |product() |product() |Product() |Product()
+
+|all() |all() |all() |all() |All() |All()
+
+|any() |any() |any() |any() |Any() |Any()
+
+|none() |none() |none() |none() |None() |None()
+
+|concat() |concat() |concat() |concat() |Concat() |Concat()
+
+|intersect() |intersect() |intersect() |intersect() |Intersect()
+|Intersect()
+
+|union() |union() |union() |union() |Union() |Union()
+
+|difference() |difference() |difference() |difference() |Difference()
+|Difference()
+
+|disjunct() |disjunct() |disjunct() |disjunct() |Disjunct()
+|Disjunct()
+|===
+
+'''''
+
+== Function Definitions
+
+=== `length()` [[length_list]]
+
+Returns the length of a list in the incoming traverser
+
+==== Signature(s)
+
+`length()`
+
+==== Parameters
+
+None
+
+==== Allowed incoming traverser types
+
+Array data types. If non-array data types are passed in then an
+`IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+A Long value representing the number of items in an array or the number
+of characters in a string
+
+....
+g.inject([1, 2]).length()
+==>2
+....
+
+=== `reverse()` [[reverse_list]]
+
+Returns the value of the incoming list in reverse order
+
+==== Signature(s)
+
+`reverse()`
+
+==== Parameters
+
+None
+
+==== Allowed incoming traverser types
+
+Array data types. If non-array data types are passed in then an
+`IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+An array in reverse order.
+
+....
+g.inject([1,2]).reverse()
+==>[2, 1]
+....
+
+=== `remove()` [[remove_list]]
+
+Removes the first element from the incoming list where the value equals
+the specified value
+
+==== Signature(s)
+
+`remove(value)`
+
+`remove(Traversal)`
+
+==== Parameters
+
+* value - The value to remove
+
+==== Allowed incoming traverser types
+
+Array data types. If non-array data types are passed in then an
+`IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+An array value representing the new list
+
+....
+g.inject([1,2]).remove(1)
+==>[2]
+....
+
+=== `indexOf()` [[indexOf_list]]
+ 
+Returns the first occurrence of the `value` in the incoming array
+
+==== Signature(s)
+
+`indexOf(value)`
+
+`indexOf(Traversal)`
+
+==== Parameters
+
+* value - The value to locate
+
+==== Allowed incoming traverser types
+
+Array data types. If non-array data types are passed in then an
+`IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+A long representing the index of the first occurrence of the value
+(zero-based). If the values does not exist then `null` is returned
+
+....
+g.inject([1,2]).indexOf(1)
+==>0
+....
+
+=== `product()` [[product_list]]
+
+Returns the cartesian product of two lists
+
+==== Signature(s)
+
+`product(value)`
+
+`product(Traversal)`
+
+==== Parameters
+
+* value - An array
+
+==== Allowed incoming traverser types
+
+Array data types. If non-array data types are passed in then an
+`IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+A set of values where each value contains the cartesian product of two
+lists
+
+....
+g.inject([1,2]).product([3,4])
+==>[[1,3], [1,4], [2,3], [2,4]]
+....
+
+=== `any()` [[any_list]]
+
+Returns true if any items in the array `value` exist in the input
+
+==== Signature(s)
+
+`any(value)`
+
+`any(Traversal)`
+
+==== Parameters
+
+* value - An array of the items to check in the incoming list
+
+==== Allowed incoming traverser types
+
+Array data types. If non-array data types are passed in then an
+`IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+True if any values from one list are in the other, False otherwise
+
+....
+g.inject([1,2]).any([1])
+==>true
+g.inject([1,2]).any([3])
+==>false
+....
+
+=== `all()` [[all_list]]
+
+Returns true if all items in the array `value` exist in the input
+
+==== Signature(s)
+
+`all(value)`
+
+`all(Traversal)`
+
+==== Parameters
+
+* value - An array of the items to check in the incoming list
+
+==== Allowed incoming traverser types
+
+Array data types. If non-array data types are passed in then an
+`IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+True if all values from one list are in the other, False otherwise
+
+....
+g.inject([1,2]).all([1])
+==>true
+g.inject([1,2]).all([1, 3])
+==>false
+g.inject([1,2]).all([3])
+==>false
+....
+
+=== `none()` [[none_list]]
+
+Returns true if no items in the array `value` exist in the input
+
+==== Signature(s)
+
+`none(value)`
+
+`none(Traversal)`
+
+==== Parameters
+
+* value - An array of the items to check in the incoming list
+
+==== Allowed incoming traverser types
+
+Array data types. If non-array data types are passed in then an
+`IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+True if no values from one list are in the other, False otherwise
+
+....
+g.inject([1,2]).none([1])
+==>false
+g.inject([1,2]).none([1, 3])
+==>false
+g.inject([1,2]).none([3])
+==>true
+....
+
+=== `concat()` [[concat_list]]
+
+Returns the concatenation of the incoming array and the traversal or
+array value passed as a parameter. This will return all values,
+including duplicates.
+
+==== Signature(s)
+
+`concat(value)`
+
+`concat(Traversal)`
+
+==== Parameters
+
+* value - An array of the items to check in the incoming list
+
+==== Allowed incoming traverser types
+
+Array data types. If non-array data types are passed in then an
+`IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+An array containing the values of the concatenation of the two lists
+
+....
+g.inject([1,2]).concat([3])
+==>[1, 2, 3]
+g.inject([1,2]).concat([1, 4])
+==>[1, 2, 1, 4]
+g.V().has('age', 29).values('age').dedup().fold().concat(V().has('age', 30).values('age').dedup().fold())
+==>[29, 30]
+....
+
+=== `union()` [[union_list]]
+
+Returns the union of the incoming array and the traversal or array value
+passed as a parameter. This will return an array of unique values
+
+==== Signature(s)
+
+`union(value)`
+
+`union(Traversal)`
+
+==== Parameters
+
+* value - An array of the items to check in the incoming list
+
+==== Allowed incoming traverser types
+
+Array data types. If non-array data types are passed in then an
+`IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+An array containing the unique values of the union of the two lists
+
+....
+g.inject([1,2]).union([1])
+==>[1, 2]
+g.inject([1,2]).union([1, 4])
+==>[1, 2, 4]
+g.V().has('age', 29).values('age').dedup().fold().union(V().has('age', 30).values('age').dedup().fold())
+==>[29, 30]
+....
+
+=== `intersect()` [[intersect_list]]
+
+Returns the intersection of the incoming array and the traversal or
+array value passed as a parameter. This will return an array of unique
+values
+
+==== Signature(s)
+
+`intersect(value)`
+
+`intersect(Traversal)`
+
+==== Parameters
+
+* value - An array of the items to check in the incoming list
+
+==== Allowed incoming traverser types
+
+Array data types. If non-array data types are passed in then an
+`IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+An array containing the unique values of the intersection of the two
+lists
+
+....
+g.inject([1,2]).intersect([1])
+==>[1]
+g.inject([1,2]).intersect([1, 2, 3])
+==>[1, 2]
+g.V().has('age', 29).values('age').dedup().fold().intersect(V().has('age', 30).values('age').dedup().fold())
+==>[]
+....
+
+=== `difference()` [[difference_list]]
+
+Returns the difference of the incoming array and the traversal or array
+value passed as a parameter. This will return an array of unique values
+
+==== Signature(s)
+
+`difference(value)`
+
+`difference(Traversal)`
+
+==== Parameters
+
+* value - An array of the items to check in the incoming list
+
+==== Allowed incoming traverser types
+
+Array data types. If non-array data types are passed in then an
+`IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+An array containing the different values of the intersection of the two
+lists
+
+....
+g.inject([1,2]).difference([1])
+==>[2]
+g.inject([1,2]).difference([1, 2, 3])
+==>[3]
+g.V().has('age', 29).values('age').dedup().fold().difference(V().has('age', 30).values('age').dedup().fold())
+==>[29, 30]
+....
+
+....
+
+=== `disjunct()` [[disjunct_list]]
+
+Returns the disjunct set of the incoming array and the traversal or array
+value passed as a parameter. This will return an array of unique values
+
+==== Signature(s)
+
+`disjunct(value)`
+
+`disjunct(Traversal)`
+
+==== Parameters
+
+* value - An array of the items to check in the incoming list
+
+==== Allowed incoming traverser types
+
+Array data types. If non-array data types are passed in then an
+`IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+An array containing the different values of the intersection of the two
+lists
+
+....
+g.inject([1,2]).disjunct([1])
+==>[2]
+g.inject([1,2,4]).disjunct([1, 2, 3])
+==>[3, 4]
+
+
+
+== Date Manipulation functions in TinkerPop [[date-function-syntax]]
+
+One of the common gaps that user's find when using Gremlin is that there
+is a lack of date manipulation capabilities within the language itself.
+This requires that users use closures to handle many common manipulation
+options that users want to do on data in the graph. This is a problem
+for many users as many of the providers prevent the use of arbitrary
+closures due to the security risks so for these users there is no way to
+manipulate strings directly.
+
+=== Proposal
+
+The proposal here is to add a set of steps to handle common datetime
+manipulation requests from users, the details for each are discussed
+below:
+
+* <<asDate, asDate()>>
+* <<dateAdd, dateAdd()>>
+* <<dateDiff, dateDiff()>>
+
+=== Gremlin Language Variant Function Names
+
+[cols=",,,,,",options="header",]
+|===
+|Groovy |Java |Python |JavaScript |.NET |Go
+|asDate() |asDate() |as_date() |asDate() |AsDate() |AsDate()
+|dateAdd() |dateAdd() |date_add() |dateAdd() |DateAdd() |DateAdd()
+|dateDiff() |dateDiff() |date_diff() |dateDiff() |DateDiff() |DateDiff()
+|===
+
+== Function Definitions
+
+=== `asDate()` [[asDate]]
+
+Returns the value of the incoming traverser as an ISO-8601 date
+
+==== Signature(s)
+
+`asDate()`
+
+`asDate(Scope)`
+
+==== Parameters
+
+* Scope - Scope Enum
+
+==== Allowed incoming traverser types
+
+Any data type that can be parsed into an ISO-8601 date. If an
+unsupported types is passed in then an `IllegalArgumentException` will
+be thrown
+
+==== Expected Output
+
+A Date value representing the ISO-8601 value of the traverser being
+passed in as shown below:
+
+[cols=",,",options="header",]
+|===
+|Incoming Datatype |Example Query |Example Output
+|Integer |`g.inject(0).asDate()` |1900-01-01T00:00:00Z
+
+|Float |`g.inject(29.0).asDate()` |1900-01-01T00:00:00Z
+
+|String |`g.inject('1/1/1900').asDate()` |1900-01-01T00:00:00Z
+
+|UUID |`g.inject(UUID.randomUUID()).asDate()`
+|`IllegalArgumentException`
+
+|Map
+|`g.inject([["id": 1], ["id": 2, "something":"anything"]]).asDate()`
+|`IllegalArgumentException`]
+
+|Datetime |`g.inject(datetime()).asDate()` |Sun Nov 04 00:00:00 UTC 2018
+
+|List |`g.inject([1,2,3]).asDate()` |`IllegalArgumentException`
+
+|List (Local Scope) |`g.inject([1,2,3]).asDate(local)`
+|`IllegalArgumentException`
+
+|Vertex |`g.V(1).asDate()` |`IllegalArgumentException`
+
+|Edge |`g.E(7).asDate()` |`IllegalArgumentException`
+
+|Property |`g.V(1).properties('age').asDate()`
+|`IllegalArgumentException`
+
+|null |`g.V().group().by('foo').select(keys).asDate()`
+|`IllegalArgumentException`
+|===
+
+=== `dateAdd()` [[dateAdd]]
+
+Returns the value with the addition of the `value` number of units as
+specified by the `DateToken`
+
+==== Signature(s)
+
+`dateAdd(DateToken, value)`
+
+`dateAdd(Scope, DateToken, value))`
+
+==== Parameters
+
+* DateToken - DateToken Enum
+* value - The number of units, specified by the Datetime Token, to add to
+the incoming values
+
+==== Allowed incoming traverser types
+
+Datetime data types. If non-array data types are passed in then an
+`IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+A Datetime with the value added.
+
+....
+g.inject(datetime()).dateAdd(DT.days, 7)
+==> 2018-03-22
+g.inject(datetime()).dateAdd(DT.days, -7)
+==> 2018-03-8
+g.inject([datetime(), datetime()]).dateAdd(local, DT.days, 7)
+==> [2018-03-22, 2018-03-22]
+....
+
+=== `dateDiff()` [[dateDiff]]
+
+Returns the difference between two Datetimes in epoch time
+
+==== Signature(s)
+
+`dateDiff(value)`
+
+`dateDiff(Traversal)`
+
+`dateDiff(Scope, value))`
+
+==== Parameters
+
+* value - The Datetime to find the difference from
+
+==== Allowed incoming traverser types
+
+Datetime data types. If non-array data types are passed in then an
+`IllegalArgumentException` will be thrown
+
+==== Expected Output
+
+The epoch time difference between the two values
+
+....
+g.inject(datetime()).dateDiff(datetime().dateAdd(DT.days, 7))
+==> 604800
+g.inject(datetime()).dateDiff(datetime().dateAdd(DT.days, 7))
+==> -604800
+g.inject([datetime(), datetime()]).dateDiff(local, DT.days, 7)
+==> [604800, 604800]
+....
diff --git a/docs/src/dev/future/proposal-arrow-flight-2.asciidoc b/docs/src/dev/future/proposal-arrow-flight-2.asciidoc
new file mode 100644
index 0000000..0849c08
--- /dev/null
+++ b/docs/src/dev/future/proposal-arrow-flight-2.asciidoc
@@ -0,0 +1,77 @@
+////
+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.
+////
+image::apache-tinkerpop-logo.png[width=500,link="https://tinkerpop.apache.org"]
+
+*x.y.z - Proposal 2*
+
+= Gremlin Arrow Flight
+
+== Introduction
+Gremlin Server and Clients are based on WebSockets with a https://tinkerpop.apache.org/docs/current/dev/provider/#_graph_driver_provider_requirements/[custom sub-protocol] and serialization to GraphSON and GraphBinary. Developers for each driver must implement those protocols from scratch and there is a limited amount of code which is being reused (only 3rd party WebSocket libraries are currently reused in the client variants). The protocol implementation is a complicated and error-prone process, so most drivers only support some subset of Gremlin Server features. The maintenance cost is also constantly increasing with the number of new client variants being added to TinkerPop.
+
+== Motivation
+We would like to propose a solution to reduce maintenance and simplify the development of the client drivers by using a standard protocol based on the Apache Arrow Flight. As Arrow Flight is implemented in the most common languages like C++, C#, Java and Python we anticipate a larger amount of existing codebase can be reused which would help to reduce maintenance costs in the future. Also, we can reuse some other Arrow Flight features like authentication and error handling.
+
+== Assumptions
+
+* Need to reuse existing code as much as possible
+* It is desirable, but not necessary, to maintain compatibility with existing drivers
+* To simplify development at the initial stage, we will reuse existing serialization mechanism
+
+== Requirements
+
+* Gremlin Server and drivers should replace the network layer with Arrow Flight
+* No significant drop in performance
+* Gremlin Arrow must pass the Gherkin test suite
+
+== Specifications
+=== Design Overview
+
+The main idea is to replace the transport layer with FlightServer and FlightClient. They support asynchronous data transfer, splitting data into chunks, and authorization. While Arrow Flight typically requires schema, in a short term we can proceed with implementation using existing serializers and GraphBinary format. By using GraphBinary we will not have all capabilities that Arrow Flight provides out of the box, like efficient compression. However, in future, we see the value of adding capabilities to generate a schema from the server-side, and that can enable additional use cases.
+
+==== First stage: replace transport layer, but keep serializers
+
+Arrow Flight Server and Client implementations can be used to replace network code for Gremlin Server and GLV's.
+
+Pros:
+* Reduction of the code base to be developed and maintained
+* A relatively low number of modifications
+
+Cons:
+* We may observe reduced performance due to schema transfer and other overhead
+* Still need to support GraphBinary serialization
+
+==== Second stage: replace transport layer, make dynamic schema generation and use native Arrow structures for data transmission
+
+In addition, need to rework the serialization and add schema generation.
+We can use a user-provided schema to simplify development and reduce the size of the data transferred.
+
+Pros:
+* Greater reduction of the codebase to be developed and maintained
+* Performance and memory usage will be improved for large data sets due to Arrow Flight optimizations and the ability to transfer data in parallel
+* No need to support GraphBinary and GraphSON serialization protocols 
+* We can use Arrow libraries to import and export data, supported several popular formats like CSV, JSON, Apache Parquet, Apache ORC
+
+Cons:
+* Reduced performance for small result sets
+* Can be complicated and expensive to generate a schema for each request. Can be solved with intoducing schema to Tinkerpop.
+
+Open question: how to efficiently serialize heterogeneous data, for example `g.inject(1,"str",new HashMap<>())`.
+
+== Similar solutions
+
+link:https://github.com/neo4j-field/neo4j-arrow/[neo4j-arrow]
diff --git a/docs/src/dev/future/proposal-transaction-4.asciidoc b/docs/src/dev/future/proposal-transaction-4.asciidoc
new file mode 100644
index 0000000..5a63e10
--- /dev/null
+++ b/docs/src/dev/future/proposal-transaction-4.asciidoc
@@ -0,0 +1,137 @@
+////
+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.
+////
+image::apache-tinkerpop-logo.png[width=500,link="https://tinkerpop.apache.org"]
+
+*x.y.z - Proposal 4*
+
+== TinkerGraph Transaction Support
+
+=== Introduction
+Now, if you need to use transactions in TinkerPop, the only solution is to use the Neo4j plugin. Unfortunately, this plugin has not been updated for a long time and is only compatible with Neo4j version 3.4, which reached end of life in March 2020. Gremlin cannot be used as a replacement for other graphs that support transactions.
+
+=== Motivation
+* Users will be able to use transactions without the outdated Neo4j plugin.
+* Test framework simplification.
+* A more robust Gremlin Server setup out-of-the-box.
+* A better learning experience for new users.
+* A less complicated transaction story for new users.
+* A better test graph that is more readily swappable with other graphs.
+
+=== Assumptions
+
+* Need to reuse existing code as much as possible.
+* Users should be able to work both with and without transactions.
+* Transaction implementation should not have additional external dependencies.
+* Existing drivers should work without changes.
+
+=== Specifications
+==== Design Overview
+The main changes relate to TinkerGraph, need to make a similar solution but with transaction support. Also TinkerGraph by default will have 2 configurations on Gremlin Server and users themselves will choose what they need, TinkerGraph or TinkerTransactionGraph.
+Locks will be write-only to reduce the impact of transactions on performance. In this case the isolation level will be `read committed`, the same as now with the Neo4j plugin. 
+Only ThreadLocalTransaction is planned, therefore embedded graph transactions may not be fully supported.
+
+==== Overview of changes to code base
+===== ElementContainer
+Storage for current Element value and ThreadLocal updated value with `isDeleted` flag. Similar for `Vertices` and `Edges`.
+[code]
+----
+class ElementContainer {
+    Vertex current;
+    ThreadLocal<Vertex> transactionUpdatedValue;
+    ThreadLocal<Boolean> isDeleted;
+}
+----
+
+===== TinkerTransactionGraph
+Vertices and Edges will store with version number and dirty transaction values
+`Map<Object, ElementContainer> vertices` where `Object` is Vertex Id.
+Shared code with TinkerGraph will be moved to AbstractTinkerGraph.
+
+===== TinkerTransactionElement
+Add `currentVersion` to all TinkerElements. This is the number of the transaction that last updated it.
+
+===== TinkerThreadLocalTransaction
+Extension of AbstractThreadLocalTransaction. Add a unique transaction number. Can use `AtomicLong.incrementAndGet`
+
+===== Graph Feature files
+Add TinkerTransactionGraphFeatures, TinkerTransactionGraphVertexFeatures, TinkerTransactionGraphEdgeFeatures, TinkerTransactionGraphGraphFeatures, TinkerTransactionGraphVertexPropertyFeatures.
+
+==== CRUD operations without transaction
+1. Wrap into transaction
+2. Commit
+
+==== CRUD operations with transaction
+===== Create
+Add new ElementContainer to `vertices` and `edges` in TinkerTransactionGraph.
+
+==== Read
+Read values from `vertices` ElementContainer, `transactionUpdatedValue` if present, otherwise `current`.
+if `isDeleted` flag is set, then the element is deleted in transaction and should be skipped.
+
+===== Update
+Update corresponding ElementContainer  in `vertices`.
+
+===== Delete
+Set `isDeleted` flag in ElementContainer  in `vertices`.
+
+==== Transaction flows
+===== Commit flow
+To reduce lock time double-checked locking used.
+1. Make list of all affected elements sorted by transaction#. The reason is to reduce the lock time.
+2. If any has a newer version, then fail.
+3. Try to lock all Vertices/Edges changed in transaction. For vertex/edge delete operation also need to lock adjacent edges/vertices. Lock is for write operations only. If some Vertex/Edge is already locked then fail.
+4. Check versions again, fail if some element is updated. Code: `Vertices.get(id).current()).currentVersion() !=Vertices.get(id).transactionUpdatedValue().currentVersion()`
+5. For all Elements replace current version with value updated in transaction (or remove Element on Delete operation). Cleanup `transactionUpdatedValue`.
+6. Change version of all updated Elements.
+7. Unlock.
+8. Update indexes if needed.
+
+===== Rollback
+Cleanup `transactionUpdatedValue` in `vertices`
+
+===== Error
+On any error, including transaction conflict:
+1. Rollback
+2. Throw exception
+
+===== Timeout
+Add transactionWatchdog which will rollback locked/expired transactions. Similar to `Session.touch`.
+1. If the transaction was open longer than some preconfigured (default 10-20 minutes?) time.
+2. If the transaction start commit, but not finish (default 1-2 seconds?).
+
+===== Examples of conflict resolution
+* tx1 adds a property to v1, tx2 deletes v1 (same for edges)
+transaction that executed first will set the lock on v1, second transaction will fail on one of steps 2-4.
+* tx1 adds an edge from v1 to v2, tx2 deletes v1 or v2
+If tx1 try to commit first: tx1 add edge, tx2 delete v1 AND all edges including newly added.
+If tx2 try to commit first: tx2 deletes v1 or v2, tx1 will fail on step 1.
+* tx1 changes a Cardinality.single property to x, tx2 changes the same Cardinality.single property to y
+Last transaction will fail on step 2 or 4.
+* tx1 adds a new vertex v1, tx2 adds the same vertex (same for edges)
+Last transaction will fail on step 2 or 4 or 5.
+* tx1 removes vertex v1, tx2 removes the same vertex (same for edges)
+Both transactions will be successful. 
+* tx1 adds vertex v1, tx2 removes vertex v1 (same for edges)
+If v1 exists before and tx1 commit first: tx1 fail on step 5
+If v1 exists before and tx2 commit first: tx1 fail on step 2 or 4
+If v1 not exists before and tx1 commit first: tx1 ok; tx2 depends on commit time, ok when tx1 finished and fail on step 2 or 4 otherwise.
+If v1 not exists before and tx2 commit first: tx2 ok, tx1 ok
+
+
+==== Additional changes
+Split TinkerFactory into AbstractTinkerFactory and TinkerFactory, add TinkerTransactionGraphFactory.
+Transfer responsibility of graph update operations from static TinkerHelper to TinkerGraph/TinkerTransactionGraph.
diff --git a/docs/src/dev/io/graphson.asciidoc b/docs/src/dev/io/graphson.asciidoc
index f0aa50d..b473285 100644
--- a/docs/src/dev/io/graphson.asciidoc
+++ b/docs/src/dev/io/graphson.asciidoc
@@ -22,7 +22,7 @@
 import java.time.*
 mapper = GraphSONMapper.build().
                         addRegistry(TinkerIoRegistry.instance()).
-                        addCustomModule(new org.apache.tinkerpop.gremlin.driver.ser.AbstractGraphSONMessageSerializerV1d0.GremlinServerModule()).
+                        addCustomModule(new org.apache.tinkerpop.gremlin.util.ser.AbstractGraphSONMessageSerializerV1d0.GremlinServerModule()).
                         version(GraphSONVersion.V1_0).create().createMapper()
 graph = TinkerFactory.createTheCrew()
 g = graph.traversal()
@@ -94,10 +94,10 @@
   writer.write("\n")
   writer.write("=== ResponseMessage\n\n")
   msg = ResponseMessage.build(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).
-                        code(org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode.AUTHENTICATE).create()
+                        code(org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode.AUTHENTICATE).create()
   writer.write(toJson(msg, "Authentication Challenge", "When authentication is enabled, an initial request to the server will result in an authentication challenge. The typical response message will appear as follows, but handling it could be different dependending on the SASL implementation (e.g. multiple challenges may be requested in some cases, but not in the default provided by Gremlin Server)."))
   msg = ResponseMessage.build(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).
-                        code(org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode.SUCCESS).
+                        code(org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode.SUCCESS).
                         result(Arrays.asList(graph.vertices().next())).create()
   writer.write(toJson(msg, "Standard Result", "The following `ResponseMessage` is a typical example of the typical successful response Gremlin Server will return when returning results from a script."))
 
@@ -107,7 +107,7 @@
                         addRegistry(TinkerIoRegistryV2d0.instance()).
                         typeInfo(TypeInfo.PARTIAL_TYPES).
                         addCustomModule(GraphSONXModuleV2d0.build().create(false)).
-                        addCustomModule(new org.apache.tinkerpop.gremlin.driver.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
+                        addCustomModule(new org.apache.tinkerpop.gremlin.util.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
                         version(GraphSONVersion.V2_0).create().createMapper()
 
 file = new File("io-output/out-graphson-2d0-partial.txt")
@@ -191,10 +191,10 @@
   writer.write("\n")
   writer.write("=== ResponseMessage\n\n")
   msg = ResponseMessage.build(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).
-                        code(org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode.AUTHENTICATE).create()
+                        code(org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode.AUTHENTICATE).create()
   writer.write(toJson(msg, "Authentication Challenge", "When authentication is enabled, an initial request to the server will result in an authentication challenge. The typical response message will appear as follows, but handling it could be different dependending on the SASL implementation (e.g. multiple challenges may be requested in some cases, but no in the default provided by Gremlin Server).", "v2d0-partial"))
   msg = ResponseMessage.build(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).
-                        code(org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode.SUCCESS).
+                        code(org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode.SUCCESS).
                         result(Arrays.asList(graph.vertices().next())).create()
   writer.write(toJson(msg, "Standard Result", "The following `ResponseMessage` is a typical example of the typical successful response Gremlin Server will return when returning results from a script.", "v2d0-partial"))
 
@@ -236,7 +236,7 @@
                         addRegistry(TinkerIoRegistryV2d0.instance()).
                         typeInfo(TypeInfo.NO_TYPES).
                         addCustomModule(GraphSONXModuleV2d0.build().create(false)).
-                        addCustomModule(new org.apache.tinkerpop.gremlin.driver.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
+                        addCustomModule(new org.apache.tinkerpop.gremlin.util.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
                         version(GraphSONVersion.V2_0).create().createMapper()
 
 file = new File("io-output/out-graphson-2d0-no-types.txt")
@@ -320,10 +320,10 @@
   writer.write("\n")
   writer.write("=== ResponseMessage\n\n")
   msg = ResponseMessage.build(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).
-                        code(org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode.AUTHENTICATE).create()
+                        code(org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode.AUTHENTICATE).create()
   writer.write(toJson(msg, "Authentication Challenge", "When authentication is enabled, an initial request to the server will result in an authentication challenge. The typical response message will appear as follows, but handling it could be different dependending on the SASL implementation (e.g. multiple challenges maybe requested in some cases, but no in the default provided by Gremlin Server).", "v2d0-no-types"))
   msg = ResponseMessage.build(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).
-                        code(org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode.SUCCESS).
+                        code(org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode.SUCCESS).
                         result(Arrays.asList(graph.vertices().next())).create()
   writer.write(toJson(msg, "Standard Result", "The following `ResponseMessage` is a typical example of the typical successful response Gremlin Server will return when returning results from a script.", "v2d0-no-types"))
 
diff --git a/docs/src/dev/io/index.asciidoc b/docs/src/dev/io/index.asciidoc
index 25c1ad7..b49816b 100644
--- a/docs/src/dev/io/index.asciidoc
+++ b/docs/src/dev/io/index.asciidoc
@@ -14,12 +14,15 @@
 See the License for the specific language governing permissions and
 limitations under the License.
 ////
+
+:docinfo: shared
+:docinfodir: ../../
+:toc-position: left
+
 image::apache-tinkerpop-logo.png[width=500,link="https://tinkerpop.apache.org"]
 
 *x.y.z*
 
-:toc-position: left
-
 = IO Reference
 
 image:gremlin-io2.png[width=300]
diff --git a/docs/src/dev/provider/index.asciidoc b/docs/src/dev/provider/index.asciidoc
index b276621..9cb37ae 100644
--- a/docs/src/dev/provider/index.asciidoc
+++ b/docs/src/dev/provider/index.asciidoc
@@ -14,12 +14,15 @@
 See the License for the specific language governing permissions and
 limitations under the License.
 ////
+
+:docinfo: shared
+:docinfodir: ../../
+:toc-position: left
+
 image::apache-tinkerpop-logo.png[width=500,link="https://tinkerpop.apache.org"]
 
 *x.y.z*
 
-:toc-position: left
-
 = Introduction
 
 image:tinkerpop-cityscape.png[]
@@ -191,7 +194,8 @@
 * `VertexProperty`
 ** This interface is both a `Property` and an `Element` as `VertexProperty` is a first-class graph element in that it
 can have its own properties (i.e. meta-properties). Even if the implementation does not intend to support
-meta-properties, the `VertexProperty` needs to be implemented as an `Element`.
+meta-properties, the `VertexProperty` needs to be implemented as an `Element`. `VertexProperty` should return empty
+iterable for properties if meta-properties is not supported.
 
 [[olap-implementations]]
 ==== OLAP Implementations
@@ -1096,6 +1100,9 @@
 NOTE: Please refer to the link:https://tinkerpop.apache.org/docs/x.y.z/dev/io[IO Reference Documentation] for more
 examples of `RequestMessage` and `ResponseMessage` instances.
 
+NOTE: Tinkerpop provides a test server which may be useful for testing drivers. Details can be found
+link:https://tinkerpop.apache.org/docs/current/dev/developer/#gremlin-socket-server-tests[here]
+
 === OpProcessors Arguments
 
 The following sections define a non-exhaustive list of available operations and arguments for embedded `OpProcessors`
diff --git a/docs/src/docinfo.html b/docs/src/docinfo.html
new file mode 100644
index 0000000..8524b44
--- /dev/null
+++ b/docs/src/docinfo.html
@@ -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.
+-->
+<!-- Matomo -->
+<script>
+    var _paq = window._paq = window._paq || [];
+    /* We explicitly disable cookie tracking to avoid privacy issues */
+    _paq.push(['disableCookies']);
+    /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
+    _paq.push(['trackPageView']);
+    _paq.push(['enableLinkTracking']);
+    (function() {
+        var u="https://analytics.apache.org/";
+        _paq.push(['setTrackerUrl', u+'matomo.php']);
+        _paq.push(['setSiteId', '27']);
+        var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
+        g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
+    })();
+</script>
+<!-- End Matomo Code -->
\ No newline at end of file
diff --git a/docs/src/index.asciidoc b/docs/src/index.asciidoc
index 3fd5b01..69e3582 100644
--- a/docs/src/index.asciidoc
+++ b/docs/src/index.asciidoc
@@ -15,6 +15,8 @@
 limitations under the License.
 ////
 
+:docinfo: shared
+
 image::apache-tinkerpop-logo.png[width=500]
 
 *x.y.z*
diff --git a/docs/src/recipes/index.asciidoc b/docs/src/recipes/index.asciidoc
index 5e6556a..fb2765a 100644
--- a/docs/src/recipes/index.asciidoc
+++ b/docs/src/recipes/index.asciidoc
@@ -14,12 +14,15 @@
 See the License for the specific language governing permissions and
 limitations under the License.
 ////
+
+:docinfo: shared
+:docinfodir: ../
+:toc-position: left
+
 image::apache-tinkerpop-logo.png[width=500,link="https://tinkerpop.apache.org"]
 
 *x.y.z*
 
-:toc-position: left
-
 = Recipes
 
 image:gremlin-chef.png[width=120,float=left] All programming languages tend to have
diff --git a/docs/src/reference/gremlin-applications.asciidoc b/docs/src/reference/gremlin-applications.asciidoc
index 2ee5c21..6d70cf3 100644
--- a/docs/src/reference/gremlin-applications.asciidoc
+++ b/docs/src/reference/gremlin-applications.asciidoc
@@ -498,10 +498,10 @@
 [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
-[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] AbstractChannelizer - Configured application/vnd.gremlin-v3.0+json with org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0
+[INFO] AbstractChannelizer - Configured application/json with org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0
+[INFO] AbstractChannelizer - Configured application/vnd.graphbinary-v1.0 with org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1
+[INFO] AbstractChannelizer - Configured application/vnd.graphbinary-v1.0-stringd with org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1
 [INFO] GremlinServer$1 - Gremlin Server configured with worker thread pool of 1, gremlin pool of 4 and boss thread pool of 1.
 [INFO] GremlinServer$1 - Channel started at port 8182.
 ----
@@ -1141,7 +1141,7 @@
 
 [source,yaml]
 ----
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0 }
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0 }
 ----
 
 Gremlin Server is configured by default with GraphSON 3.0 as shown above. It has the following configuration option:
@@ -1161,8 +1161,8 @@
 
 [source,yaml]
 ----
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0 }
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0 }
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV1d0 }
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0 }
 ----
 
 In the above situation, both `GraphSONMessageSerializerV1d0` and `GraphSONMessageSerializerV3d0` each bind to the
@@ -1172,9 +1172,9 @@
 
 [source,text]
 ----
-[INFO] AbstractChannelizer - Configured application/json with org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0
-[INFO] AbstractChannelizer - Configured application/vnd.gremlin-v3.0+json with org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0
-[INFO] AbstractChannelizer - application/json already has org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0 configured - it will not be replaced by org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0, change order of serialization configuration if this is not desired.
+[INFO] AbstractChannelizer - Configured application/json with org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV1d0
+[INFO] AbstractChannelizer - Configured application/vnd.gremlin-v3.0+json with org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0
+[INFO] AbstractChannelizer - application/json already has org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV1d0 configured - it will not be replaced by org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0, change order of serialization configuration if this is not desired.
 ----
 
 Given the above, using GraphSON 3.0 under this configuration will require that the user specific the type:
@@ -1200,7 +1200,7 @@
 format itself is described in the link:https://tinkerpop.apache.org/docs/x.y.z/dev/io/#graphbinary[IO Documentation].
 
 [source,yaml]
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1 }
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1 }
 
 It has the MIME type of `application/vnd.graphbinary-v1.0` and the following configuration options:
 
@@ -1689,7 +1689,7 @@
 ----
 package org.yourpackage;
 
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.verification.VertexProgramRestrictionStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
@@ -1810,7 +1810,7 @@
      * {@link AuthorizationException} if this is not the case.
      *
      * @param user {@link AuthenticatedUser} that needs authorization.
-     * @param msg {@link RequestMessage} in which the {@link org.apache.tinkerpop.gremlin.driver.Tokens}.ARGS_GREMLIN argument can contain an arbitrary succession of script statements.
+     * @param msg {@link RequestMessage} in which the {@link org.apache.tinkerpop.gremlin.util.Tokens}.ARGS_GREMLIN argument can contain an arbitrary succession of script statements.
      */
     public void authorize(final AuthenticatedUser user, final RequestMessage msg) throws AuthorizationException {
         if (!usernamesSandbox.contains(user.getName())) {
@@ -2265,10 +2265,23 @@
 With the type of request and detachment model in mind, it is now possible to discuss how best to consider element
 properties in relation to them all in concert.
 
-By default, Gremlin Server sample configurations utilize `ReferenceElementStrategy` when creating the out-of-the-box
-`GraphTraversalSource`. As the name suggests, this means that elements will be detached by reference and will
-therefore not have properties included. The relevant configuration from the Gremlin Server initialization script looks
-like this:
+By default, Gremlin Server configuration returns all properties.
+
+To manage properties for each request you can use the <<configuration-steps-with,with()>> configuration option 
+`materializeProperties`
+
+[source,groovy]
+----
+g.with('materializeProperties', 'tokens').V()
+----
+
+The `tokens` value for the `materializeProperties` means that only `id` and `label` should be returned.
+Another option, `all`, can be used to indicate that all properties should be returned and is the default value.
+
+In some cases it can be inconvenient to load Elements with properties due to large data size or for compatibility reasons.
+That can be solved by utilizing `ReferenceElementStrategy` when creating the out-of-the-box `GraphTraversalSource`.
+As the name suggests, this means that elements will be detached by reference and will therefore not have properties 
+included. The relevant configuration from the Gremlin Server initialization script looks like this:
 
 [source,groovy]
 ----
@@ -2276,39 +2289,12 @@
 ----
 
 This configuration is global to Gremlin Server and therefore all methods of connection will always return elements
-without properties. If this strategy is not included, then there are other considerations to take into account such as
-the connection type (i.e. script or bytecode) and the serializer.
-
-For script-based requests, users should take care when returning graph elements. By default, elements will be returned
-as "detached elements" and depending on the serializer being used those detached elements may or may not have their
-properties carried with them. Gryo and GraphSON serializers will write all properties in the return payload in this
-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.
-
-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
-as it won't arrive on the client side without that declaration.
+without properties. If this strategy is not included, then elements will be returned with properties.
 
 Ultimately, the detachment model should have little impact to Gremlin usage if the best practice of specifying only
-the data required by the application is adhered to. In other words, while there may be a difference in the contents
-of return values for these traversals:
+the data required by the application is adhered to. 
 
-[source,java]
-----
-// properties returned from g.V().hasLabel('person') because this is using the
-// Script API with full detachment
-Cluster cluster = Cluster.open();
-Client client = cluster.connect();
-ResultSet results = client.submit("g.V().hasLabel('person')");
-
-// no properties returned from g.V().hasLabel("person") because this is using
-// Bytecode API with reference detachment
-GraphTraversalSource g = traversal().withRemote('conf/remote-graph.properties');
-List<Vertex> results = g.V().hasLabel("person").toList();
-----
-
-There is no difference if re-written using the best practice of requesting only the data the application needs:
+The best practice of requesting only the data the application needs:
 
 [source,java]
 ----
@@ -2322,10 +2308,8 @@
 
 Both of the above requests return a list of `Map` instances that contain the `id`, `label` and the "name" property.
 
-TIP: The example graph configurations pre-packaged with Gremlin Server utilize `ReferenceElementStrategy`
-which convert all graph elements to references by initializing "g" using
-`withStrategies(ReferenceElementStrategy.instance()`. Consider utilizing `ReferenceElementStrategy` whenever creating
-a `GraphTraversalSource` in Java to ensure the most portable Gremlin.
+TIP: Consider utilizing `ReferenceElementStrategy` whenever creating a `GraphTraversalSource` in Java to ensure 
+the most portable Gremlin.
 
 NOTE: For those interested, please see link:https://lists.apache.org/thread.html/e959e85d4f8b3d46d281f2742a6e574c7d27c54bfc52f802f7c04af3%40%3Cdev.tinkerpop.apache.org%3E[this post]
 to the TinkerPop dev list which outlines the full history of this issue and related concerns.
diff --git a/docs/src/reference/index.asciidoc b/docs/src/reference/index.asciidoc
index 2253991..f655621 100644
--- a/docs/src/reference/index.asciidoc
+++ b/docs/src/reference/index.asciidoc
@@ -14,12 +14,15 @@
 See the License for the specific language governing permissions and
 limitations under the License.
 ////
+
+:docinfo: shared
+:docinfodir: ../
+:toc-position: left
+
 image::apache-tinkerpop-logo.png[width=500,link="https://tinkerpop.apache.org"]
 
 *x.y.z*
 
-:toc-position: left
-
 include::preface.asciidoc[]
 
 include::intro.asciidoc[]
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index 2a99b36..99cbf29 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -1238,16 +1238,18 @@
 [[e-step]]
 === E Step
 
-The `E()`-step is meant to read edges from the graph and is usually used to start a `GraphTraversal`. Unlike the related
-<<v-step,V()>> it cannot be used mid-traversal.
+The `E()`-step is meant to read edges from the graph and is usually used to start a `GraphTraversal`, but can also
+be used mid-traversal.
 
 [gremlin-groovy,modern]
 ----
 g.E(11) <1>
 g.E().hasLabel('knows').has('weight', gt(0.75))
+g.inject(1).coalesce(E().hasLabel("knows"), addE("knows").from(V().has("name","josh")).to(V().has("name","vadas"))) <2>
 ----
 
 <1> Find the edge by its unique identifier (i.e. `T.id`) - not all graphs will use a numeric value for their identifier.
+<2> Get edges with label `knows`, if there is none then add new one between `josh` and `vadas`.
 
 *Additional References*
 
@@ -1761,6 +1763,10 @@
 writing perspective is not that different in there are no parallel operations in play, however streaming the output
 to disk requires a single pass of the data without high memory requirements for larger datasets.
 
+IMPORTANT: Default graph formats don't contain information about property cardinality, so it is up to the graph
+provider to choose the appropriate one. You will see a warning message if the chosen cardinality is SINGLE
+while your graph input contains multiple values for that property.
+
 In general, TinkerPop recommends that users examine the native bulk import/export tools of the graph implementation
 that they choose. Those tools will often outperform the `io()`-step and perhaps be easier to use with a greater
 feature set. That said, graph providers do have the option to optimize `io()` to back it with their own
diff --git a/docs/src/tutorials/getting-started/index.asciidoc b/docs/src/tutorials/getting-started/index.asciidoc
index 043e0ae..5288e3e 100644
--- a/docs/src/tutorials/getting-started/index.asciidoc
+++ b/docs/src/tutorials/getting-started/index.asciidoc
@@ -15,6 +15,9 @@
 limitations under the License.
 ////
 
+:docinfo: shared
+:docinfodir: ../../
+
 image::apache-tinkerpop-logo.png[width=500,link="https://tinkerpop.apache.org"]
 
 *x.y.z*
diff --git a/docs/src/tutorials/gremlin-language-variants/index.asciidoc b/docs/src/tutorials/gremlin-language-variants/index.asciidoc
index d26544c..db1797d 100644
--- a/docs/src/tutorials/gremlin-language-variants/index.asciidoc
+++ b/docs/src/tutorials/gremlin-language-variants/index.asciidoc
@@ -14,6 +14,10 @@
 See the License for the specific language governing permissions and
 limitations under the License.
 ////
+
+:docinfo: shared
+:docinfodir: ../../
+
 image::apache-tinkerpop-logo.png[width=500,link="https://tinkerpop.apache.org"]
 
 *x.y.z*
diff --git a/docs/src/tutorials/gremlins-anatomy/index.asciidoc b/docs/src/tutorials/gremlins-anatomy/index.asciidoc
index abc037a..27146f9 100644
--- a/docs/src/tutorials/gremlins-anatomy/index.asciidoc
+++ b/docs/src/tutorials/gremlins-anatomy/index.asciidoc
@@ -15,6 +15,9 @@
 limitations under the License.
 ////
 
+:docinfo: shared
+:docinfodir: ../../
+
 image::apache-tinkerpop-logo.png[width=500,link="https://tinkerpop.apache.org"]
 
 *x.y.z*
diff --git a/docs/src/tutorials/the-gremlin-console/index.asciidoc b/docs/src/tutorials/the-gremlin-console/index.asciidoc
index ad04607..e566e62 100644
--- a/docs/src/tutorials/the-gremlin-console/index.asciidoc
+++ b/docs/src/tutorials/the-gremlin-console/index.asciidoc
@@ -15,6 +15,9 @@
 limitations under the License.
 ////
 
+:docinfo: shared
+:docinfodir: ../../
+
 image::apache-tinkerpop-logo.png[width=500,link="https://tinkerpop.apache.org"]
 
 *x.y.z*
diff --git a/docs/src/upgrade/index.asciidoc b/docs/src/upgrade/index.asciidoc
index 512ec7a..419ee28 100644
--- a/docs/src/upgrade/index.asciidoc
+++ b/docs/src/upgrade/index.asciidoc
@@ -14,10 +14,13 @@
 See the License for the specific language governing permissions and
 limitations under the License.
 ////
-image::apache-tinkerpop-logo.png[width=500,link="https://tinkerpop.apache.org"]
 
+:docinfo: shared
+:docinfodir: ../
 :toc-position: left
 
+image::apache-tinkerpop-logo.png[width=500,link="https://tinkerpop.apache.org"]
+
 = TinkerPop Upgrade Information
 
 This document helps users of Apache TinkerPop™ to understand the changes that come with each software release.  It
@@ -25,6 +28,8 @@
 equally useful to TinkerPop providers, who build libraries and other systems on the core APIs and protocols that
 TinkerPop exposes.
 
+include::release-3.7.x.asciidoc[]
+
 include::release-3.6.x.asciidoc[]
 
 include::release-3.5.x.asciidoc[]
diff --git a/docs/src/upgrade/release-3.7.x.asciidoc b/docs/src/upgrade/release-3.7.x.asciidoc
new file mode 100644
index 0000000..5ba1594
--- /dev/null
+++ b/docs/src/upgrade/release-3.7.x.asciidoc
@@ -0,0 +1,203 @@
+////
+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.7.0
+
+image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/images/gremlin-running.png[width=185]
+
+*NOT OFFICIALLY NAMED YET*
+
+== TinkerPop 3.7.0
+
+*Release Date: NOT OFFICIALLY RELEASED YET*
+
+Please see the link:https://github.com/apache/tinkerpop/blob/3.7.0/CHANGELOG.asciidoc#release-3-7-0[changelog] for a complete list of all the modifications that are part of this release.
+
+=== Upgrading for Users
+
+==== Properties on Elements
+
+===== Introduction
+
+By default properties on `Element` are now returned for OLTP requests. Gremlin Server 3.5 and 3.6 can return properties only in some special cases. 
+More history details about serialization of properties can be found in the link:https://lists.apache.org/thread/xltcon4zxnwq4fyw2r2126syyrqm8spy[Stephen's post].
+
+===== Behavior for OLAP queries
+
+Queries still won't return properties on Elements. The main reason for this is performance considerations.
+If you need to get a property, then this can be explicitly configured with `HaltedTraverserStrategy`
+
+[source,java]
+----
+  g.withComputer().withStrategies(HaltedTraverserFactoryStrategy.detached())
+----
+
+===== Output comparison for Gremlin Server 3.5/3.6 and 3.7
+
+Let's take a closer look at a Javascript GLV code example in 3.6 and 3.7:
+
+[source,javascript]
+----
+  const client = new Client('ws://localhost:8182/gremlin',{traversalSource: 'gmodern'});
+  await client.open();
+  const result = await client.submit('g.V(1)');
+  console.log(JSON.stringify(result.first()));
+  await client.close();
+----
+
+The result will be different depending on the version of Gremlin Server.
+For 3.5/3.6:
+[source,json]
+----
+  {"id":1,"label":"person"}
+----
+
+For 3.7:
+[source,json]
+----
+  {"id":1,"label":"person","properties":{"name":[{"id":0,"label":"name","value":"marko","key":"name"}],"age":[{"id":1,"label":"age","value":29,"key":"age"}]}}
+---- 
+
+===== Enabling the previous behavior
+
+The GLVs in 3.5/3.6 will not be able to work correctly with properties on Elements. If you don't need to get properties then you can do one of the following:
+
+* To configure Gremlin Server to not return properties, update Gremlin Server initialization script with `ReferenceElementStrategy`.
+This method is better to use with 3.5/3.6 GLVs.
+For example 
+[source,groovy]
+----
+globals << [g : traversal().withEmbedded(graph).withStrategies(ReferenceElementStrategy)]
+----
+
+* Use config per request `with('materializeProperties', 'tokens')`
+[source,csharp]
+----
+g.With("materializeProperties", "tokens").V(1).Next()
+----
+
+===== Possible issues
+
+ReferenceElement-type objects are no longer returned - you get a DetachedElement from remote requests. If you have not been implementing the `Element` interfaces then you will need to update the code to use interfaces like `Vertex` and `Edge`.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2824[TINKERPOP-2824]
+
+
+==== Gremlin.NET: Nullable Annotations
+
+Gremlin.NET now uses link:https://learn.microsoft.com/en-us/dotnet/csharp/nullable-references#nullable-variable-annotations[nullable annotations]
+to state wether an argument or a return value can be null or not. This should make it much less likely to get a
+`NullReferenceException` from Gremlin.NET.
+
+This change required to make some breaking changes but most users should not be affected by this as the breaking
+changes are limited to APIs that are mostly intended for graph driver providers.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2348[TINKERPOP-2348]
+
+==== Removed connectOnStartup javascript
+
+Removed the `connectOnStartup` option for Gremlin Javascript API to resolve potential `unhandledRejection` and race
+conditions. New `DriverRemoteConnection` objects no longer initiate connection by default at startup. Call `open()`
+explicitly if one wishes to manually connect on startup.
+
+For example:
+
+[source,javascript]
+----
+const drc = new DriverRemoteConnection(url);
+drc.open().catch(err => {
+   // Handle error upon open.
+})
+----
+
+==== Creation of New `gremlin-util` Module
+
+`gremlin-driver` has been refactored and several classes have been extracted to a new `gremlin-util` module. Any classes
+which are utilized by both `gremlin-driver` and `gremlin-server` have been extracted to `gremlin-util`. This includes
+the entire `tinkerpop.gremlin.driver.ser` and `tinkerpop.gremlin.driver.message` packages as well as
+`tinkerpop.gremlin.driver.MessageSerializer` and `tinkerpop.gremlin.driver.Tokens`. For a full list of the migrated
+classes, see: link:https://issues.apache.org/jira/browse/TINKERPOP-2819[TINKERPOP-2819].
+All migrated classes have had their packages updated to reflect this change. For these classes, packages have changed
+from `tinkerpop.gremlin.driver.*` to `tinkerpop.gremlin.util.*`. For example
+`org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1` has been updated to
+`org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1`. All imports of these classes should be updated
+to reflect this change. All server config files which declare a list of serializers should also be updated to
+reflect the new location of serializer classes.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2819[TINKERPOP-2819]
+
+==== Removal of `gremlin-driver` from `gremlin-server`
+
+`gremlin-driver` is no longer a dependency of `gremlin-server` and thus will no longer be packaged in server
+distributions. Any app which makes use of both `gremlin-driver` and `gremlin-server` will now need to directly
+include both modules.
+
+==== Building and Running with JDK 17
+
+You can now run TinkerPop with Java 17. Be advised that there are some issues with reflection and so you may need to
+either --add-opens or --add-exports certain modules to enable it to work with Java 17. This mostly affects the Kryo
+serialization library which is used with OLAP. If you use OLTP, then you may not need to add any of these options to
+the JVM. The following are only examples used by TinkerPop's automated tests and are placed here for convenience.
+
+    --add-opens=java.base/java.io=ALL-UNNAMED
+    --add-opens=java.base/java.nio=ALL-UNNAMED
+    --add-opens=java.base/sun.nio.cs=ALL-UNNAMED
+    --add-opens=java.base/java.lang=ALL-UNNAMED
+    --add-opens=java.base/java.lang.invoke=ALL-UNNAMED
+    --add-opens=java.base/java.lang.reflect=ALL-UNNAMED
+    --add-opens=java.base/java.util=ALL-UNNAMED
+    --add-opens=java.base/java.util.concurrent=ALL-UNNAMED
+    --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED
+    --add-opens=java.base/java.net=ALL-UNNAMED
+
+=== Upgrading for Providers
+
+==== Graph Driver Providers
+
+===== Gremlin.NET: Nullable Reference Types
+
+Enabling nullable reference types comes with some breaking changes in Gremlin.NET which can affect driver providers.
+
+GraphBinary APIs changed to make better use of nullable reference types. Instead of one method `WriteValueAsync` and
+one method `ReadValueAsync`, there are now methods `WriteNullableValueAsync` and `ReadNullableValueAsync` that allow
+`null` values and methods `WriteNonNullableValueAsync` and `ReadNonNullableValueAsync` that do not allow `null` values.
+
+Some `set` property accessors were removed from some pure data classes in the `Structure` and the `Driver.Messages`
+namespaces to initialize these properties directly from the constructor which ensures that they are really not `null`.
+We also used this opportunity to convert some of these pure data classes into a `record`.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2348[TINKERPOP-2348]
+
+===== Reworked Gremlin Socket Server
+
+The `SimpleSocketServer` from `gremlin-driver` has been brought into a new module `gremlin-tools/gremlin-socket-server`
+and it has been adapted to be usable by all drivers for testing. See more about creating gremlin socket server tests
+link:https://tinkerpop.apache.org/docs/x.y.z/dev/developer/#gremlin-socket-server-tests[here].
+
+===== Mid-traversal E()
+
+Traversals now support mid-traversal E()-steps.
+
+Prior to this change you were limited to using E()-step only at the start of traversal, but now you can this step in
+the middle. This improvement makes it easier for users to build certain types of queries. For example, get edges with
+label knows, if there is none then add new one between josh and vadas.
+
+`g.inject(1).coalesce(E().hasLabel("knows"), addE("knows").from(V().has("name","josh")).to(V().has("name","vadas")))`
+
+Another reason is to make E() and V() steps equivalent in terms of use in the middle of traversal.
+
+See link:https://issues.apache.org/jira/browse/TINKERPOP-2798[TINKERPOP-2798]
diff --git a/gremlin-annotations/pom.xml b/gremlin-annotations/pom.xml
index 97f7568..3f9128a 100644
--- a/gremlin-annotations/pom.xml
+++ b/gremlin-annotations/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>tinkerpop</artifactId>
         <groupId>org.apache.tinkerpop</groupId>
-        <version>3.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>gremlin-annotations</artifactId>
@@ -138,7 +138,7 @@
         <profile>
             <id>jdk11</id>
             <activation>
-                <jdk>11</jdk>
+                <jdk>[11,18)</jdk>
             </activation>
             <build>
                 <plugins>
diff --git a/gremlin-archetype/gremlin-archetype-dsl/pom.xml b/gremlin-archetype/gremlin-archetype-dsl/pom.xml
index a83a6f9..dee245b 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.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>gremlin-archetype-dsl</artifactId>
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 1dabb27..c37584d 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
@@ -73,7 +73,7 @@
         <profile>
             <id>jdk11</id>
             <activation>
-                <jdk>11</jdk>
+                <jdk>[11,18)</jdk>
             </activation>
             <build>
                 <plugins>
diff --git a/gremlin-archetype/gremlin-archetype-server/pom.xml b/gremlin-archetype/gremlin-archetype-server/pom.xml
index 7bde67b..b8c3f97 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.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>gremlin-archetype-server</artifactId>
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 2e57f1c..d18e8e3 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
@@ -83,7 +83,7 @@
         <profile>
             <id>jdk11</id>
             <activation>
-                <jdk>11</jdk>
+                <jdk>[11,18)</jdk>
             </activation>
             <build>
                 <plugins>
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 3ba912d..9d5278b 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,7 +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.GraphBinaryMessageSerializerV1 }
+  - { className: org.apache.tinkerpop.gremlin.util.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 63b1be6..8b643d7 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.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>gremlin-archetype-tinkergraph</artifactId>
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 27f3209..9bd2658 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
@@ -67,7 +67,7 @@
         <profile>
             <id>jdk11</id>
             <activation>
-                <jdk>11</jdk>
+                <jdk>[11,18)</jdk>
             </activation>
             <build>
                 <plugins>
diff --git a/gremlin-archetype/pom.xml b/gremlin-archetype/pom.xml
index 7c70e97..2a35046 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.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>gremlin-archetype</artifactId>
diff --git a/gremlin-console/bin/gremlin.sh b/gremlin-console/bin/gremlin.sh
index 9429409..d6bc18d 120000
--- a/gremlin-console/bin/gremlin.sh
+++ b/gremlin-console/bin/gremlin.sh
@@ -1 +1 @@
-../target/apache-tinkerpop-gremlin-console-3.6.5-SNAPSHOT-standalone/bin/gremlin.sh
\ No newline at end of file
+../target/apache-tinkerpop-gremlin-console-3.7.0-SNAPSHOT-standalone/bin/gremlin.sh
\ No newline at end of file
diff --git a/gremlin-console/conf/remote-objects.yaml b/gremlin-console/conf/remote-objects.yaml
index 70eb0fb..608f2a7 100644
--- a/gremlin-console/conf/remote-objects.yaml
+++ b/gremlin-console/conf/remote-objects.yaml
@@ -34,4 +34,4 @@
 
 hosts: [localhost]
 port: 8182
-serializer: { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1 }
\ No newline at end of file
+serializer: { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1 }
\ No newline at end of file
diff --git a/gremlin-console/conf/remote-secure.yaml b/gremlin-console/conf/remote-secure.yaml
index a29d99a..61ce00f 100644
--- a/gremlin-console/conf/remote-secure.yaml
+++ b/gremlin-console/conf/remote-secure.yaml
@@ -31,4 +31,4 @@
 connectionPool: {
   enableSsl: true,
   sslEnabledProtocols: [TLSv1.2] }
-serializer: { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}
\ No newline at end of file
+serializer: { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}
\ No newline at end of file
diff --git a/gremlin-console/conf/remote.yaml b/gremlin-console/conf/remote.yaml
index 1a43250..e0ac5c0 100644
--- a/gremlin-console/conf/remote.yaml
+++ b/gremlin-console/conf/remote.yaml
@@ -31,4 +31,4 @@
 
 hosts: [localhost]
 port: 8182
-serializer: { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}
+serializer: { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}
diff --git a/gremlin-console/pom.xml b/gremlin-console/pom.xml
index f97ed2d..7a90f3b 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.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-console</artifactId>
     <name>Apache TinkerPop :: Gremlin Console</name>
@@ -144,6 +144,11 @@
                 </exclusion>
             </exclusions>
         </dependency>
+        <dependency>
+            <groupId>org.apache.groovy</groupId>
+            <artifactId>groovy-cli-picocli</artifactId>
+            <version>${groovy.version}</version>
+        </dependency>
     </dependencies>
     <build>
         <directory>${basedir}/target</directory>
@@ -295,6 +300,10 @@
                                     <file>src/main/static/licenses/slf4j</file>
                                 </transformer>
                                 <transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
+                                    <resource>META-INF/licenses/treelayout</resource>
+                                    <file>src/main/static/licenses/treelayout</file>
+                                </transformer>
+                                <transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
                                     <resource>META-INF/licenses/logback</resource>
                                     <file>src/main/static/licenses/logback</file>
                                 </transformer>
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 f5c681f..b54396b 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
@@ -23,12 +23,16 @@
 import jline.TerminalFactory
 import jline.console.history.FileHistory
 
+import org.apache.groovy.groovysh.ExitNotification
+import org.apache.groovy.groovysh.Groovysh
+import org.apache.groovy.groovysh.InteractiveShellRunner
+import org.apache.groovy.groovysh.commands.SetCommand
 import org.apache.tinkerpop.gremlin.console.commands.BytecodeCommand
+import org.apache.tinkerpop.gremlin.console.commands.ClsCommand
 import org.apache.tinkerpop.gremlin.console.commands.GremlinSetCommand
 import org.apache.tinkerpop.gremlin.console.commands.InstallCommand
 import org.apache.tinkerpop.gremlin.console.commands.PluginCommand
 import org.apache.tinkerpop.gremlin.console.commands.RemoteCommand
-import org.apache.tinkerpop.gremlin.console.commands.ClsCommand
 import org.apache.tinkerpop.gremlin.console.commands.SubmitCommand
 import org.apache.tinkerpop.gremlin.console.commands.UninstallCommand
 import org.apache.tinkerpop.gremlin.groovy.loaders.GremlinLoader
@@ -37,11 +41,7 @@
 import org.apache.tinkerpop.gremlin.jsr223.ImportCustomizer
 import org.apache.tinkerpop.gremlin.jsr223.console.RemoteException
 import org.apache.tinkerpop.gremlin.process.traversal.Failure
-import org.apache.tinkerpop.gremlin.process.traversal.Step
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep
-import org.apache.tinkerpop.gremlin.process.traversal.translator.GroovyTranslator
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_NL_O_P_S_SE_SL_Traverser
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalExplanation
 import org.apache.tinkerpop.gremlin.structure.Edge
@@ -49,11 +49,7 @@
 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.codehaus.groovy.tools.shell.IO
-import org.codehaus.groovy.tools.shell.InteractiveShellRunner
-import org.codehaus.groovy.tools.shell.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 9782237..63b7e3a 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
@@ -19,15 +19,15 @@
 package org.apache.tinkerpop.gremlin.console
 
 import groovy.transform.ThreadInterrupt
+import org.apache.groovy.groovysh.Command
+import org.apache.groovy.groovysh.Groovysh
+import org.apache.groovy.groovysh.ParseCode
+import org.apache.groovy.groovysh.Parser
+import org.apache.groovy.groovysh.util.CommandArgumentParser
 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.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
 
 /**
  * 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 5fc7d9a..066596f 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,7 @@
  */
 package org.apache.tinkerpop.gremlin.console
 
-import org.apache.tinkerpop.gremlin.console.Preferences;
+import org.apache.groovy.groovysh.Groovysh
 import org.apache.tinkerpop.gremlin.jsr223.BindingsCustomizer
 import org.apache.tinkerpop.gremlin.jsr223.GremlinPlugin
 import org.apache.tinkerpop.gremlin.jsr223.ImportCustomizer
@@ -26,7 +26,6 @@
 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.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 ca966e5..93ae8a0 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
@@ -18,6 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.console.commands
 
+import org.apache.groovy.groovysh.ComplexCommandSupport
+import org.apache.groovy.groovysh.Groovysh
 import org.apache.tinkerpop.gremlin.console.Mediator
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal
@@ -28,8 +30,6 @@
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONXModuleV3d0
 import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper
 import org.apache.tinkerpop.shaded.jackson.databind.module.SimpleModule
-import org.codehaus.groovy.tools.shell.ComplexCommandSupport
-import org.codehaus.groovy.tools.shell.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..a7821c9 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
@@ -18,9 +18,9 @@
  */
 package org.apache.tinkerpop.gremlin.console.commands
 
+import org.apache.groovy.groovysh.CommandSupport
+import org.apache.groovy.groovysh.Groovysh
 import org.apache.tinkerpop.gremlin.console.Mediator
-import org.codehaus.groovy.tools.shell.CommandSupport
-import org.codehaus.groovy.tools.shell.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..7716727 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,11 +20,11 @@
 
 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.apache.groovy.groovysh.util.SimpleCompleter
 import org.codehaus.groovy.tools.shell.util.Preferences
-import org.codehaus.groovy.tools.shell.util.SimpleCompletor
 
 /**
  * A Gremlin-specific implementation of the {@code SetCommand} provided by Groovy.  Didn't see another way to
@@ -79,8 +79,8 @@
         }
 
         return [
-            new SimpleCompletor(loader),
-            null
+                new SimpleCompleter(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..2a3f944 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
@@ -18,15 +18,15 @@
  */
 package org.apache.tinkerpop.gremlin.console.commands
 
+import groovy.grape.Grape
+import org.apache.groovy.groovysh.CommandSupport
+import org.apache.groovy.groovysh.Groovysh
 import org.apache.tinkerpop.gremlin.console.ConsoleFs
 import org.apache.tinkerpop.gremlin.console.Mediator
 import org.apache.tinkerpop.gremlin.console.PluggedIn
-import groovy.grape.Grape
 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
 
 /**
  * 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..38ae294 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
@@ -18,10 +18,10 @@
  */
 package org.apache.tinkerpop.gremlin.console.commands
 
+import org.apache.groovy.groovysh.ComplexCommandSupport
+import org.apache.groovy.groovysh.Groovysh
 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
 
 /**
  * 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 ba98410..c25c0c4 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
@@ -18,11 +18,11 @@
  */
 package org.apache.tinkerpop.gremlin.console.commands
 
+import org.apache.groovy.groovysh.ComplexCommandSupport
+import org.apache.groovy.groovysh.Groovysh
 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
 
 /**
  * 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..a246e0e 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
@@ -18,9 +18,9 @@
  */
 package org.apache.tinkerpop.gremlin.console.commands
 
+import org.apache.groovy.groovysh.CommandSupport
+import org.apache.groovy.groovysh.Groovysh
 import org.apache.tinkerpop.gremlin.console.Mediator
-import org.codehaus.groovy.tools.shell.CommandSupport
-import org.codehaus.groovy.tools.shell.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..617064d 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
@@ -18,10 +18,10 @@
  */
 package org.apache.tinkerpop.gremlin.console.commands
 
+import org.apache.groovy.groovysh.CommandSupport
+import org.apache.groovy.groovysh.Groovysh
 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
 
 /**
  * Uninstall a maven dependency from the Console's path.
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 3eb750e..34e54f3 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
@@ -22,28 +22,28 @@
 import org.apache.tinkerpop.gremlin.driver.Cluster;
 import org.apache.tinkerpop.gremlin.driver.Host;
 import org.apache.tinkerpop.gremlin.driver.LoadBalancingStrategy;
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
 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.util.Tokens;
 import org.apache.tinkerpop.gremlin.driver.exception.ConnectionException;
 import org.apache.tinkerpop.gremlin.driver.exception.ResponseException;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseResult;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatus;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseResult;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatus;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteConnection;
 import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteTraversal;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV1d0;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV2d0;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV2d0;
-import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
-import org.apache.tinkerpop.gremlin.driver.ser.SerTokens;
-import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
-import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
+import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
+import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerGremlinV1d0;
+import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerGremlinV2d0;
+import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV1d0;
+import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV2d0;
+import org.apache.tinkerpop.gremlin.util.ser.MessageTextSerializer;
+import org.apache.tinkerpop.gremlin.util.ser.SerTokens;
+import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
+import org.apache.tinkerpop.gremlin.util.ser.Serializers;
 import org.apache.tinkerpop.gremlin.jsr223.AbstractGremlinPlugin;
 import org.apache.tinkerpop.gremlin.jsr223.DefaultImportCustomizer;
 import org.apache.tinkerpop.gremlin.jsr223.ImportCustomizer;
diff --git a/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptor.java b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptor.java
index 22ffe3c..20f20bc 100644
--- a/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptor.java
+++ b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptor.java
@@ -24,10 +24,10 @@
 import org.apache.tinkerpop.gremlin.driver.RequestOptions;
 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.util.Tokens;
 import org.apache.tinkerpop.gremlin.driver.exception.NoHostAvailableException;
 import org.apache.tinkerpop.gremlin.driver.exception.ResponseException;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.jsr223.console.GremlinShellEnvironment;
 import org.apache.tinkerpop.gremlin.jsr223.console.RemoteAcceptor;
 import org.apache.tinkerpop.gremlin.jsr223.console.RemoteException;
diff --git a/gremlin-console/src/main/static/LICENSE b/gremlin-console/src/main/static/LICENSE
index fba6db1..23d9e7c 100644
--- a/gremlin-console/src/main/static/LICENSE
+++ b/gremlin-console/src/main/static/LICENSE
@@ -217,6 +217,7 @@
      minlog (com.esotericsoftware:minlog:1.3.0 - https://github.com/EsotericSoftware/minlog)
        - shaded in gremlin-shaded to org.apache.tinkerpop.shaded.minlog
        - for details, see licenses/minlog
+     treelayout (org.abego.treelayout:org.abego.treelayout.core:1.0.3 - http://treelayout.sourceforge.net/) - for details, see licenses/treelayout
 
 ========================================================================
 MIT Licenses
diff --git a/gremlin-console/src/main/static/NOTICE b/gremlin-console/src/main/static/NOTICE
index a8856e3..2a7b9b3 100644
--- a/gremlin-console/src/main/static/NOTICE
+++ b/gremlin-console/src/main/static/NOTICE
@@ -18,15 +18,10 @@
 Copyright (c) 2008 Alexander Beider & Stephen P. Morse.
 
 ------------------------------------------------------------------------
-Apache Groovy 2.5.22 (AL ASF)
+Apache Groovy 4.0.9 (AL ASF)
 ------------------------------------------------------------------------
-This product includes/uses ANTLR (http://www.antlr2.org/)
-developed by Terence Parr 1989-2006
-
-This product bundles icons from the famfamfam.com silk icons set
-http://www.famfamfam.com/lab/icons/silk/
-Licensed under the Creative Commons Attribution Licence v2.5
-http://creativecommons.org/licenses/by/2.5/
+This product includes/uses ANTLR4 (https://github.com/antlr/antlr4)
+Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
 
 ------------------------------------------------------------------------
 Apache Ivy 2.5.1 (AL ASF)
@@ -55,7 +50,7 @@
    (Apache license)
 
 ------------------------------------------------------------------------
-Jackson-Databind and Jackson-Core 2.14.0 (Included through gremlin-shaded)
+Jackson-Databind 2.14.0 and Jackson-Core - shaded in gremlin-shaded to org.apache.tinkerpop.shaded.jackson
 ------------------------------------------------------------------------
 It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has
 been in development since 2007.
@@ -72,6 +67,6 @@
 Copyright 2014 The Netty Project
 
 ------------------------------------------------------------------------
-Objenesis 2.4 (Included through gremlin-shaded)
+Objenesis 3.3 - shaded in gremlin-shaded to org.apache.tinkerpop.shaded.objenesis
 ------------------------------------------------------------------------
-Copyright 2006-2016 Joe Walnes, Henri Tremblay, Leonardo Mesquita
+Copyright 2006-2022 Joe Walnes, Henri Tremblay, Leonardo Mesquita
diff --git a/gremlin-console/src/main/static/licenses/treelayout b/gremlin-console/src/main/static/licenses/treelayout
new file mode 100644
index 0000000..e92280d
--- /dev/null
+++ b/gremlin-console/src/main/static/licenses/treelayout
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2011, abego Software GmbH, Germany (http://www.abego.org)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+* Neither the name of the copyright holder nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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 33499d5..57b7979 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
@@ -18,16 +18,16 @@
  */
 package org.apache.tinkerpop.gremlin.console.jsr223;
 
+import org.apache.groovy.groovysh.Groovysh;
 import org.apache.tinkerpop.gremlin.TestHelper;
 import org.apache.tinkerpop.gremlin.driver.Cluster;
 import org.apache.tinkerpop.gremlin.driver.Result;
-import org.apache.tinkerpop.gremlin.driver.Tokens;
+import org.apache.tinkerpop.gremlin.util.Tokens;
 import org.apache.tinkerpop.gremlin.jsr223.console.GremlinShellEnvironment;
 import org.apache.tinkerpop.gremlin.jsr223.console.RemoteException;
 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.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 a15857a..84f4254 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
@@ -18,10 +18,10 @@
  */
 package org.apache.tinkerpop.gremlin.console.jsr223;
 
+import org.apache.groovy.groovysh.Groovysh;
 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.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 9e2a024..7781d87 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
@@ -20,12 +20,12 @@
 
 import com.github.tomakehurst.wiremock.junit.WireMockRule;
 import org.apache.commons.io.input.NullInputStream;
+import org.apache.groovy.groovysh.Groovysh;
 import org.apache.tinkerpop.gremlin.console.GremlinGroovysh;
 import org.apache.tinkerpop.gremlin.console.Mediator;
 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.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..b7753af 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
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.console.jsr223;
 
+import org.apache.groovy.groovysh.Groovysh;
 import org.apache.tinkerpop.gremlin.jsr223.console.GremlinShellEnvironment;
-import org.codehaus.groovy.tools.shell.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 07fd951..9b26f76 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
@@ -19,9 +19,9 @@
 package org.apache.tinkerpop.gremlin.console.jsr223;
 
 import org.apache.commons.io.input.NullInputStream;
+import org.apache.groovy.groovysh.Groovysh;
 import org.apache.tinkerpop.gremlin.console.PluggedIn;
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
-import org.codehaus.groovy.tools.shell.Groovysh;
 import org.codehaus.groovy.tools.shell.IO;
 import org.junit.Test;
 
diff --git a/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/gremlin-server-integration.yaml b/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/gremlin-server-integration.yaml
index 68894ff..cc60310 100644
--- a/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/gremlin-server-integration.yaml
+++ b/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/gremlin-server-integration.yaml
@@ -25,10 +25,10 @@
                org.apache.tinkerpop.gremlin.tinkergraph.jsr223.TinkerGraphGremlinPlugin: {},
                org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {classImports: [java.lang.Math], methodImports: [java.lang.Math#*]}}}}
 serializers:
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}                                                                       # application/vnd.gremlin-v3.0+gryo-stringd
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV1d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV1d0] }}  # application/vnd.gremlin-v1.0+json
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}         # application/json,application/vnd.gremlin-v3.0+json
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV2d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV2d0] }}         # application/vnd.gremlin-v2.0+json
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}                                                                       # application/vnd.gremlin-v3.0+gryo-stringd
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerGremlinV1d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV1d0] }}  # application/vnd.gremlin-v1.0+json
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}         # application/json,application/vnd.gremlin-v3.0+json
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV2d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV2d0] }}         # application/vnd.gremlin-v2.0+json
 processors:
   - { className: org.apache.tinkerpop.gremlin.server.op.session.SessionOpProcessor, config: { sessionTimeout: 28800000 }}
   - { className: org.apache.tinkerpop.gremlin.server.op.traversal.TraversalOpProcessor}
diff --git a/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/remote.yaml b/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/remote.yaml
index 68e482f..187e2c7 100644
--- a/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/remote.yaml
+++ b/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/remote.yaml
@@ -17,4 +17,4 @@
 
 hosts: [localhost]
 port: 45940
-serializer: { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}
\ No newline at end of file
+serializer: { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}
\ No newline at end of file
diff --git a/gremlin-core/pom.xml b/gremlin-core/pom.xml
index 95ec172..2e933c0 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.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-core</artifactId>
     <name>Apache TinkerPop :: Gremlin Core</name>
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinScriptChecker.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinScriptChecker.java
index 3cea1db..d744634 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinScriptChecker.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinScriptChecker.java
@@ -18,6 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.jsr223;
 
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Optional;
@@ -34,15 +36,16 @@
     /**
      * An empty result whose properties return as empty.
      */
-    public static final Result EMPTY_RESULT = new Result(null, null);
+    public static final Result EMPTY_RESULT = new Result(null, null, null);
 
     /**
      * At least one of these tokens should be present somewhere in the Gremlin string for {@link #parse(String)} to
      * take any action at all.
      */
     private static final Set<String> tokens = new HashSet<>(Arrays.asList("evaluationTimeout", "scriptEvaluationTimeout",
-                                                                          "ARGS_EVAL_TIMEOUT", "ARGS_SCRIPT_EVAL_TIMEOUT",
-                                                                          "requestId", "REQUEST_ID"));
+            "ARGS_EVAL_TIMEOUT", "ARGS_SCRIPT_EVAL_TIMEOUT", "requestId", "REQUEST_ID", "materializeProperties",
+            "ARGS_MATERIALIZE_PROPERTIES"));
+
     /**
      * Matches single line comments, multi-line comments and space characters.
      * <pre>
@@ -95,24 +98,35 @@
     private static final String requestIdTokens = "[\"']requestId[\"']|(?:Tokens\\.)?REQUEST_ID";
 
     /**
+     * Regex fragment for the materializeProperties to look for. There are basically four:
+     * <ul>
+     *     <li>{@code materializeProperties} which is a string value and thus single or double quoted</li>
+     *     <li>{@code ARGS_MATERIALIZE_PROPERTIES} which is a enum type of value which can be referenced with or without a {@code Tokens} qualifier</li>
+     * </ul>
+     */
+    private static final String materializePropertiesTokens = "[\"']materializeProperties[\"']|(?:Tokens\\.)?ARGS_MATERIALIZE_PROPERTIES";
+
+    /**
      * Matches {@code .with({timeout-token},{timeout})} with a matching group on the {@code timeout}.
-     *
+     * input: g.with('materializeProperties',100)
      * <pre>
      * From https://regex101.com/
      *
-     * \.with\((?:(?:["']evaluationTimeout["']|["']scriptEvaluationTimeout["']|(?:Tokens\.)?ARGS_EVAL_TIMEOUT|(?:Tokens\.)?ARGS_SCRIPT_EVAL_TIMEOUT),(?<to>\d*)(:?L|l)?)|(?:(?:["']requestId["']|(?:Tokens\.)?REQUEST_ID),["'](?<rid>.*?))["']\)
-     *
+     * \.with\((((?:["']materializeProperties["']|["']scriptEvaluationTimeout["']|(?:Tokens\.)?ARGS_EVAL_TIMEOUT|(?:Tokens\.)?ARGS_SCRIPT_EVAL_TIMEOUT),(?<to>\d*)(:?L|l)?)|((?:["']materializeProperties["']|(?:Tokens\.)?ARGS_MATERIALIZE_PROPERTIES),["'](?<mp>.*?)["']?)|((?:["']requestId["']|(?:Tokens\.)?REQUEST_ID),["'](?<rid>.*?)["']))\)
+     * 
      * gm
-     * 1st Alternative \.with\((?:(?:["']evaluationTimeout["']|["']scriptEvaluationTimeout["']|(?:Tokens\.)?ARGS_EVAL_TIMEOUT|(?:Tokens\.)?ARGS_SCRIPT_EVAL_TIMEOUT),(?<to>\d*)(:?L|l)?)
      * \. matches the character . with index 4610 (2E16 or 568) literally (case sensitive)
      * with matches the characters with literally (case sensitive)
      * \( matches the character ( with index 4010 (2816 or 508) literally (case sensitive)
-     * Non-capturing group (?:(?:["']evaluationTimeout["']|["']scriptEvaluationTimeout["']|(?:Tokens\.)?ARGS_EVAL_TIMEOUT|(?:Tokens\.)?ARGS_SCRIPT_EVAL_TIMEOUT),(?<to>\d*)(:?L|l)?)
-     * Non-capturing group (?:["']evaluationTimeout["']|["']scriptEvaluationTimeout["']|(?:Tokens\.)?ARGS_EVAL_TIMEOUT|(?:Tokens\.)?ARGS_SCRIPT_EVAL_TIMEOUT)
-     * 1st Alternative ["']evaluationTimeout["']
+     * 1st Capturing Group (((?:["']materializeProperties["']|["']scriptEvaluationTimeout["']|(?:Tokens\.)?ARGS_EVAL_TIMEOUT|(?:Tokens\.)?ARGS_SCRIPT_EVAL_TIMEOUT),(?<to>\d*)(:?L|l)?)|((?:["']materializeProperties["']|(?:Tokens\.)?ARGS_MATERIALIZE_PROPERTIES),["'](?<mp>.*?)["']?)|((?:["']requestId["']|(?:Tokens\.)?REQUEST_ID),["'](?<rid>.*?)["']))
+     * 1st Alternative ((?:["']materializeProperties["']|["']scriptEvaluationTimeout["']|(?:Tokens\.)?ARGS_EVAL_TIMEOUT|(?:Tokens\.)?ARGS_SCRIPT_EVAL_TIMEOUT),(?<to>\d*)(:?L|l)?)
+     * 2nd Capturing Group ((?:["']materializeProperties["']|["']scriptEvaluationTimeout["']|(?:Tokens\.)?ARGS_EVAL_TIMEOUT|(?:Tokens\.)?ARGS_SCRIPT_EVAL_TIMEOUT),(?<to>\d*)(:?L|l)?)
+     * Non-capturing group (?:["']materializeProperties["']|["']scriptEvaluationTimeout["']|(?:Tokens\.)?ARGS_EVAL_TIMEOUT|(?:Tokens\.)?ARGS_SCRIPT_EVAL_TIMEOUT)
+     * 1st Alternative ["']materializeProperties["']
      * Match a single character present in the list below ["']
      * "' matches a single character in the list "' (case sensitive)
-     * evaluationTimeout matches the characters evaluationTimeout literally (case sensitive)
+     * materializeProperties
+     *  matches the characters materializeProperties literally (case sensitive)
      * Match a single character present in the list below ["']
      * "' matches a single character in the list "' (case sensitive)
      * 2nd Alternative ["']scriptEvaluationTimeout["']
@@ -137,7 +151,7 @@
      * Named Capture Group to (?<to>\d*)
      * \d matches a digit (equivalent to [0-9])
      * * matches the previous token between zero and unlimited times, as many times as possible, giving back as needed (greedy)
-     * 2nd Capturing Group (:?L|l)?
+     * 4th Capturing Group (:?L|l)?
      * ? matches the previous token between zero and one times, as many times as possible, giving back as needed (greedy)
      * 1st Alternative :?L
      * : matches the character : with index 5810 (3A16 or 728) literally (case sensitive)
@@ -145,24 +159,29 @@
      * L matches the character L with index 7610 (4C16 or 1148) literally (case sensitive)
      * 2nd Alternative l
      * l matches the character l with index 10810 (6C16 or 1548) literally (case sensitive)
-     * 2nd Alternative (?:(?:["']requestId["']|(?:Tokens\.)?REQUEST_ID),["'](?<rid>.*?))["']\)
-     * Non-capturing group (?:(?:["']requestId["']|(?:Tokens\.)?REQUEST_ID),["'](?<rid>.*?))
-     * Non-capturing group (?:["']requestId["']|(?:Tokens\.)?REQUEST_ID)
-     * 1st Alternative ["']requestId["']
-     * 2nd Alternative (?:Tokens\.)?REQUEST_ID
+     * 2nd Alternative ((?:["']materializeProperties["']|(?:Tokens\.)?ARGS_MATERIALIZE_PROPERTIES),["'](?<mp>.*?)["']?)
+     * 5th Capturing Group ((?:["']materializeProperties["']|(?:Tokens\.)?ARGS_MATERIALIZE_PROPERTIES),["'](?<mp>.*?)["']?)
+     * Non-capturing group (?:["']materializeProperties["']|(?:Tokens\.)?ARGS_MATERIALIZE_PROPERTIES)
+     * 1st Alternative ["']materializeProperties["']
+     * 2nd Alternative (?:Tokens\.)?ARGS_MATERIALIZE_PROPERTIES
      * , matches the character , with index 4410 (2C16 or 548) literally (case sensitive)
      * Match a single character present in the list below ["']
      * "' matches a single character in the list "' (case sensitive)
-     * Named Capture Group rid (?<rid>.*?)
-     * . matches any character (except for line terminators)
-     * *? matches the previous token between zero and unlimited times, as few times as possible, expanding as needed (lazy)
+     * Named Capture Group mp (?<mp>.*?)
      * Match a single character present in the list below ["']
-     * "' matches a single character in the list "' (case sensitive)
+     * 3rd Alternative ((?:["']requestId["']|(?:Tokens\.)?REQUEST_ID),["'](?<rid>.*?)["'])
+     * 7th Capturing Group ((?:["']requestId["']|(?:Tokens\.)?REQUEST_ID),["'](?<rid>.*?)["'])
      * \) matches the character ) with index 4110 (2916 or 518) literally (case sensitive)
+     * Global pattern flags
+     * g modifier: global. All matches (don't return after first match)
+     * m modifier: multi line. Causes ^ and $ to match the begin/end of each line (not only begin/end of string)
      * </pre>
      */
     private static final Pattern patternWithOptions =
-            Pattern.compile("\\.with\\(((?:" + timeoutTokens + "),(?<to>\\d*)(:?L|l)?)|((?:" + requestIdTokens + "),[\"'](?<rid>.*?))[\"']\\)");
+            Pattern.compile("\\.with\\((((?:"
+                    + timeoutTokens + "),(?<to>\\d*)(:?L|l)?)|((?:"
+                    + materializePropertiesTokens + "),[\"'](?<mp>.*?)[\"']?)|((?:"
+                    + requestIdTokens + "),[\"'](?<rid>.*?)[\"']))\\)");
 
     /**
      * Parses a Gremlin script and extracts a {@code Result} containing properties that are relevant to the checker.
@@ -184,6 +203,7 @@
         // arguments given to Result class as null mean they weren't assigned (or the parser didn't find them somehow - eek!)
         Long timeout = null;
         String requestId = null;
+        String materializeProperties = null;
         do {
             // timeout is added up across all scripts
             final String to = m.group("to");
@@ -195,9 +215,13 @@
             // request id just uses the last one found
             final String rid = m.group("rid");
             if (rid != null) requestId = rid;
+
+            //materializeProperties just uses the last one found
+            final String mp = m.group("mp");
+            if (mp != null) materializeProperties = mp;
         } while (m.find());
 
-        return new Result(timeout, requestId);
+        return new Result(timeout, requestId, materializeProperties);
     }
 
     /**
@@ -206,33 +230,44 @@
     public static class Result {
         private final Long timeout;
         private final String requestId;
+        private final String materializeProperties;
 
-        private Result(final Long timeout, final String requestId) {
+        private Result(final Long timeout, final String requestId, final String materializeProperties) {
             this.timeout = timeout;
             this.requestId = requestId;
+            this.materializeProperties = materializeProperties;
         }
 
         /**
-         * Gets the value of the timeouts that were set using the {@code with()} source step. If there are multiple
-         * commands using this step, the timeouts are summed together.
+         * Gets the value of the timeouts that were set using the {@link GraphTraversal#with(String, Object)} source step.
+         * If there are multiple commands using this step, the timeouts are summed together.
          */
         public final Optional<Long> getTimeout() {
             return null == timeout ? Optional.empty() : Optional.of(timeout);
         }
 
         /**
-         * Gets the value of the request identifier supplied using the {@code with()} source step. If there are
-         * multiple commands using this step, the last usage should represent the id returned here.
+         * Gets the value of the request identifier supplied using the {@link GraphTraversal#with(String, Object)} source step.
+         * If there are multiple commands using this step, the last usage should represent the id returned here.
          */
         public Optional<String> getRequestId() {
             return null == requestId ? Optional.empty() : Optional.of(requestId);
         }
 
+        /**
+         * Gets the value of the materializeProperties supplied using the {@link GraphTraversal#with(String, Object)} source step.
+         * If there are multiple commands using this step, the last usage should represent the value returned here.
+         */
+        public Optional<String> getMaterializeProperties() {
+            return null == materializeProperties ? Optional.empty() : Optional.of(materializeProperties);
+        }
+
         @Override
         public String toString() {
             return "GremlinScriptChecker.Result{" +
                     "timeout=" + timeout +
                     ", requestId='" + requestId + '\'' +
+                    ", materializeProperties='" + materializeProperties + '\'' +
                     '}';
         }
     }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
index 39dac7e..4531861 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
@@ -167,6 +167,10 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	@Override public T visitTraversalMethod_E(final GremlinParser.TraversalMethod_EContext ctx) { notImplemented(ctx); return null; }
+	/**
+	 * {@inheritDoc}
+	 */
 	@Override public T visitTraversalMethod_addE_String(final GremlinParser.TraversalMethod_addE_StringContext ctx) { notImplemented(ctx); return null; }
 	/**
 	 * {@inheritDoc}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
index 78d1446..1bade7d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
@@ -68,14 +68,6 @@
     }
 
     /**
-     * @deprecated As of release 3.5.2, replaced by {@link #instance()}.
-     */
-    @Deprecated
-    public static GenericLiteralVisitor getInstance() {
-        return instance();
-    }
-
-    /**
      * Parse a string literal context and return the string literal
      */
     public static String getStringLiteral(final GremlinParser.StringBasedLiteralContext stringLiteral) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinStringConstantsVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinStringConstantsVisitor.java
index 18f1d36..8c181ca 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinStringConstantsVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinStringConstantsVisitor.java
@@ -42,13 +42,6 @@
         return instance;
     }
 
-    /**
-     * @deprecated As of release 3.5.2, replaced by {@link #instance()}
-     */
-    public static GremlinStringConstantsVisitor getInstance() {
-        return instance();
-    }
-
     @Override
     public Object visitGremlinStringConstants(final GremlinParser.GremlinStringConstantsContext ctx) {
         return visitChildren(ctx);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalFunctionVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalFunctionVisitor.java
index 71a7260..4dce5e6 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalFunctionVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalFunctionVisitor.java
@@ -40,14 +40,6 @@
     }
 
     /**
-     * @deprecated As of release 3.5.2, replaced by {@link #instance()}.
-     */
-    @Deprecated
-    public static TraversalFunctionVisitor getInstance() {
-        return instance();
-    }
-
-    /**
      * {@inheritDoc}
      */
     @Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
index 111732c..6c2a0ca2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
@@ -77,6 +77,18 @@
      * {@inheritDoc}
      */
     @Override
+    public GraphTraversal visitTraversalMethod_E(final GremlinParser.TraversalMethod_EContext ctx) {
+        if (ctx.genericLiteralList().getChildCount() != 0) {
+            return this.graphTraversal.E(GenericLiteralVisitor.getGenericLiteralList(ctx.genericLiteralList()));
+        } else {
+            return this.graphTraversal.E();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public GraphTraversal visitTraversalMethod_addV_Empty(final GremlinParser.TraversalMethod_addV_EmptyContext ctx) {
         return this.graphTraversal.addV();
     }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalPredicateVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalPredicateVisitor.java
index e454bd5..9095421 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalPredicateVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalPredicateVisitor.java
@@ -36,14 +36,6 @@
         return instance;
     }
 
-    /**
-     * @deprecated As of release 3.5.2, replaced by {@link #instance()}.
-     */
-    @Deprecated
-    public static TraversalPredicateVisitor getInstance() {
-        return instance();
-    }
-
     private TraversalPredicateVisitor() {}
 
     /**
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 7fc1b39..4251683 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
@@ -332,6 +332,21 @@
     }
 
     /**
+     * A {@code E} step is usually used to start a traversal but it may also be used mid-traversal.
+     *
+     * @param edgeIdsOrElements edges to inject into the traversal
+     * @return the traversal with an appended {@link GraphStep}
+     * @see <a href="http://tinkerpop.apache.org/docs/${project.version}/reference/#e-step" target="_blank">Reference Documentation - E Step</a>
+     * @since 3.7.0
+     */
+    public default GraphTraversal<S, Edge> E(final Object... edgeIdsOrElements) {
+        // a single null is [null]
+        final Object[] ids = null == edgeIdsOrElements ? new Object[] { null } : edgeIdsOrElements;
+        this.asAdmin().getBytecode().addStep(Symbols.E, ids);
+        return this.asAdmin().addStep(new GraphStep<>(this.asAdmin(), Edge.class, false, ids));
+    }
+
+    /**
      * Map the {@link Vertex} to its adjacent vertices given a direction and edge labels.
      *
      * @param direction  the direction to traverse from the current vertex
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
index 6274b45..e0d5136 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
@@ -130,6 +130,13 @@
     }
 
     /**
+     * @see GraphTraversal#E(Object...)
+     */
+    public static <A> GraphTraversal<A, Edge> E(final Object... edgeIdsOrElements) {
+        return __.<A>start().E(edgeIdsOrElements);
+    }
+
+    /**
      * @see GraphTraversal#to(Direction, String...)
      */
     public static GraphTraversal<Vertex, Vertex> to(final Direction direction, final String... edgeLabels) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/VertexProperty.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/VertexProperty.java
index 4460f7d..ff50166 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/VertexProperty.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/VertexProperty.java
@@ -104,7 +104,7 @@
         }
 
         public static UnsupportedOperationException metaPropertiesNotSupported() {
-            return new UnsupportedOperationException("Properties on a vertex property is not supported");
+            return new UnsupportedOperationException("Adding properties to a vertex property is not supported");
         }
     }
 }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EdgeSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EdgeSerializer.java
index de88180..71992ac 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EdgeSerializer.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EdgeSerializer.java
@@ -18,15 +18,17 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io.binary.types;
 
+import org.apache.commons.collections.IteratorUtils;
+import org.apache.tinkerpop.gremlin.structure.Property;
 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;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.io.Buffer;
-import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceEdge;
-import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceVertex;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge;
 
 import java.io.IOException;
+import java.util.List;
 
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)
@@ -41,20 +43,17 @@
         final Object id = context.read(buffer);
         final String label = context.readValue(buffer, String.class, false);
 
-        final ReferenceVertex inV = new ReferenceVertex(context.read(buffer),
-                                                        context.readValue(buffer, String.class, false));
-        final ReferenceVertex outV = new ReferenceVertex(context.read(buffer),
-                                                         context.readValue(buffer, String.class, false));
+        final Object inVId = context.read(buffer);
+        final String inVLabel = context.readValue(buffer, String.class, false);
+        final Object outVId = context.read(buffer);
+        final String outVLabel = context.readValue(buffer, String.class, false);
 
-        // discard the parent vertex - we only send "references so this should always be null, but will we change our
-        // minds someday????
+        // discard the parent vertex
         context.read(buffer);
 
-        // discard the properties - as we only send "references" this should always be null, but will we change our
-        // minds some day????
-        context.read(buffer);
+        final List<Property> properties = context.read(buffer);
 
-        return new ReferenceEdge(id, label, inV, outV);
+        return new DetachedEdge(id, label, properties, outVId, outVLabel, inVId, inVLabel);
     }
 
     @Override
@@ -68,11 +67,14 @@
         context.write(value.outVertex().id(), buffer);
         context.writeValue(value.outVertex().label(), buffer, false);
 
-        // we don't serialize the parent Vertex for edges. they are "references", but we leave a place holder
-        // here as an option for the future as we've waffled this soooooooooo many times now
+        // we don't serialize the parent Vertex for edges.
         context.write(null, buffer);
-        // we don't serialize properties for graph vertices/edges. they are "references", but we leave a place holder
-        // here as an option for the future as we've waffled this soooooooooo many times now
-        context.write(null, buffer);
+        if (value.properties() == null) {
+            context.write(null, buffer);
+        }
+        else {
+            final List<?> asList = IteratorUtils.toList(value.properties());
+            context.write(asList, buffer);
+        }
     }
 }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/VertexPropertySerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/VertexPropertySerializer.java
index bb9ba8b..a09db5f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/VertexPropertySerializer.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/VertexPropertySerializer.java
@@ -18,14 +18,17 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io.binary.types;
 
+import org.apache.commons.collections.IteratorUtils;
+import org.apache.tinkerpop.gremlin.structure.Property;
 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;
 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 import org.apache.tinkerpop.gremlin.structure.io.Buffer;
-import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceVertexProperty;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty;
 
 import java.io.IOException;
+import java.util.List;
 
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)
@@ -38,17 +41,20 @@
 
     @Override
     protected VertexProperty readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException {
-        final VertexProperty v = new ReferenceVertexProperty<>(context.read(buffer),
-                context.readValue(buffer, String.class, false),
-                context.read(buffer));
+        final DetachedVertexProperty.Builder builder = DetachedVertexProperty.build()
+                .setId(context.read(buffer))
+                .setLabel(context.readValue(buffer, String.class, false))
+                .setValue(context.read(buffer));
 
         // discard the parent vertex - we only send "references"
         context.read(buffer);
 
-        // discard the properties - as we only send "references" this should always be null, but will we change our
-        // minds some day????
-        context.read(buffer);
-        return v;
+        final List<Property> properties = context.read(buffer);
+        if (properties != null && !properties.isEmpty()) {
+            for (Property p : properties) builder.addProperty(p);
+        }
+
+        return builder.create();
     }
 
     @Override
@@ -57,10 +63,10 @@
         context.writeValue(value.label(), buffer, false);
         context.write(value.value(), buffer);
 
-        // we don't serialize the parent vertex even as a "reference", but, let's hold a place for it
+        // we don't serialize the parent vertex, let's hold a place for it
         context.write(null, buffer);
-        // we don't serialize properties for graph elements. they are "references", but we leave a place holder
-        // here as an option for the future as we've waffled this soooooooooo many times now
-        context.write(null, buffer);
+
+        final List<?> asList = IteratorUtils.toList(value.properties());
+        context.write(asList, buffer);
     }
 }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/VertexSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/VertexSerializer.java
index 18909f3..01e3d87 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/VertexSerializer.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/VertexSerializer.java
@@ -18,14 +18,20 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io.binary.types;
 
+import org.apache.commons.collections.IteratorUtils;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 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;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.io.Buffer;
-import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceVertex;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
 
 import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)
@@ -37,19 +43,23 @@
 
     @Override
     protected Vertex readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException {
-        final Vertex v = new ReferenceVertex(context.read(buffer), 
-                                             context.readValue(buffer, String.class, false));
-        
-        // discard the properties - as we only send "references" this should always be null, but will we change our
-        // minds some day????
-        context.read(buffer);
-        return v;
+        final Object id = context.read(buffer);
+        final String label = context.readValue(buffer, String.class, false);
+        final List<VertexProperty> properties = context.read(buffer);
+
+        return new DetachedVertex(id, label, properties);
     }
 
     @Override
     protected void writeValue(final Vertex value, final Buffer buffer, final GraphBinaryWriter context) throws IOException {
         context.write(value.id(), buffer);
         context.writeValue(value.label(), buffer, false);
-        context.write(null, buffer);
+        if (value.properties() == null) {
+            context.write(null, buffer);
+        }
+        else {
+            final List<?> asList = IteratorUtils.toList(value.properties());
+            context.write(asList, buffer);
+        }
     }
 }
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 3004251..b9d2551 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
@@ -423,10 +423,10 @@
             // placeholder serializers for classes that don't live here in core. this will allow them to be used if
             // present  or ignored if the class isn't available. either way the registration numbers are held as
             // placeholders so that the format stays stable
-            tryAddDynamicType(this, "org.apache.tinkerpop.gremlin.driver.message.RequestMessage",
-                    "org.apache.tinkerpop.gremlin.driver.ser.RequestMessageGryoSerializer", 167);
-            tryAddDynamicType(this, "org.apache.tinkerpop.gremlin.driver.message.ResponseMessage",
-                    "org.apache.tinkerpop.gremlin.driver.ser.ResponseMessageGryoSerializer", 169);
+            tryAddDynamicType(this, "org.apache.tinkerpop.gremlin.util.message.RequestMessage",
+                    "org.apache.tinkerpop.gremlin.util.ser.RequestMessageGryoSerializer", 167);
+            tryAddDynamicType(this, "org.apache.tinkerpop.gremlin.util.message.ResponseMessage",
+                    "org.apache.tinkerpop.gremlin.util.ser.ResponseMessageGryoSerializer", 169);
 
             tryAddDynamicType(this, "org.apache.tinkerpop.gremlin.sparql.process.traversal.strategy.SparqlStrategy",
                     null, 184);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/Attachable.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/Attachable.java
index 3cd76f2..701121f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/Attachable.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/Attachable.java
@@ -27,8 +27,14 @@
 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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.function.Function;
 
@@ -43,6 +49,8 @@
  */
 public interface Attachable<V> {
 
+    Logger logger = LoggerFactory.getLogger(Attachable.class);
+
     /**
      * Get the raw object trying to be attached.
      *
@@ -291,12 +299,21 @@
             final Vertex vertex = hostGraph.features().vertex().willAllowId(baseVertex.id()) ?
                     hostGraph.addVertex(T.id, baseVertex.id(), T.label, baseVertex.label()) :
                     hostGraph.addVertex(T.label, baseVertex.label());
-            baseVertex.properties().forEachRemaining(vp -> {
-                final VertexProperty vertexProperty = hostGraph.features().vertex().properties().willAllowId(vp.id()) ?
-                        vertex.property(hostGraph.features().vertex().getCardinality(vp.key()), vp.key(), vp.value(), T.id, vp.id()) :
-                        vertex.property(hostGraph.features().vertex().getCardinality(vp.key()), vp.key(), vp.value());
-                vp.properties().forEachRemaining(p -> vertexProperty.property(p.key(), p.value()));
-            });
+            final Map<String, List<VertexProperty<Object>>> propertyMap = new HashMap<>();
+            baseVertex.properties().forEachRemaining(vp -> propertyMap.computeIfAbsent(vp.key(), k -> new ArrayList<>()).add(vp));
+            for (Map.Entry<String, List<VertexProperty<Object>>> entry : propertyMap.entrySet()) {
+                final VertexProperty.Cardinality cardinality = hostGraph.features().vertex().getCardinality(entry.getKey());
+                if (VertexProperty.Cardinality.single == cardinality && entry.getValue().size() > 1) {
+                    logger.warn("{} has SINGLE cardinality but with more than one value: {}. Only last value will be retained.",
+                        entry.getKey(), entry.getValue());
+                }
+                for (VertexProperty<Object> vp : entry.getValue()) {
+                    final VertexProperty<Object> vertexProperty = hostGraph.features().vertex().properties().willAllowId(vp.id()) ?
+                        vertex.property(cardinality, vp.key(), vp.value(), T.id, vp.id()) :
+                        vertex.property(cardinality, vp.key(), vp.value());
+                    vp.properties().forEachRemaining(p -> vertexProperty.property(p.key(), p.value()));
+                }
+            }
             return vertex;
         }
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/detached/DetachedEdge.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/detached/DetachedEdge.java
index 25e846d..1014e0e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/detached/DetachedEdge.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/detached/DetachedEdge.java
@@ -25,11 +25,12 @@
 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.javatuples.Pair;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -89,6 +90,24 @@
         }
     }
 
+    public DetachedEdge(final Object id, final String label,
+                        final List<Property> properties,
+                        final Object outVId, final String outVLabel,
+                        final Object inVId, final String inVLabel) {
+        super(id, label);
+        this.outVertex = new DetachedVertex(outVId, outVLabel, Collections.emptyMap());
+        this.inVertex = new DetachedVertex(inVId, inVLabel, Collections.emptyMap());
+        if (properties != null && !properties.isEmpty()) {
+            this.properties = new HashMap<>();
+            properties.iterator().forEachRemaining(property -> {
+                if (!this.properties.containsKey(property.key())) {
+                    this.properties.put(property.key(), new ArrayList());
+                }
+                this.properties.get(property.key()).add(property);
+            });
+        }
+    }
+
     @Override
     public String toString() {
         return StringFactory.edgeString(this);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/detached/DetachedVertex.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/detached/DetachedVertex.java
index 25bdbae..f331d8d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/detached/DetachedVertex.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/detached/DetachedVertex.java
@@ -86,6 +86,19 @@
         }
     }
 
+    public DetachedVertex(final Object id, final String label, final List<VertexProperty> properties) {
+        super(id, label);
+        if (properties != null && !properties.isEmpty()) {
+            this.properties = new HashMap<>();
+            properties.iterator().forEachRemaining(property -> {
+                if (!this.properties.containsKey(property.key())) {
+                    this.properties.put(property.key(), new ArrayList());
+                }
+                this.properties.get(property.key()).add(property);
+            });
+        }
+    }
+
     @Override
     public <V> VertexProperty<V> property(final String key, final V value) {
         throw Element.Exceptions.propertyAdditionNotSupported();
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/detached/DetachedVertexProperty.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/detached/DetachedVertexProperty.java
index d9b917c..1b70c1c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/detached/DetachedVertexProperty.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/util/detached/DetachedVertexProperty.java
@@ -25,6 +25,7 @@
 import org.apache.tinkerpop.gremlin.structure.util.Host;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -67,7 +68,8 @@
 
         if (null != properties && !properties.isEmpty()) {
             this.properties = new HashMap<>();
-            properties.entrySet().iterator().forEachRemaining(entry -> this.properties.put(entry.getKey(), Collections.singletonList(new DetachedProperty<>(entry.getKey(), entry.getValue(), this))));
+            properties.entrySet().iterator().forEachRemaining(entry -> this.properties.put(entry.getKey(),
+                    Collections.singletonList(new DetachedProperty<>(entry.getKey(), entry.getValue(), this))));
         }
     }
 
@@ -81,7 +83,8 @@
 
         if (null != properties && !properties.isEmpty()) {
             this.properties = new HashMap<>();
-            properties.entrySet().iterator().forEachRemaining(entry -> this.properties.put(entry.getKey(), Collections.singletonList(new DetachedProperty<>(entry.getKey(), entry.getValue(), this))));
+            properties.entrySet().iterator().forEachRemaining(entry -> this.properties.put(entry.getKey(),
+                    Collections.singletonList(new DetachedProperty<>(entry.getKey(), entry.getValue(), this))));
         }
     }
 
@@ -129,7 +132,11 @@
     @Override
     void internalAddProperty(final Property p) {
         if (null == properties) properties = new HashMap<>();
-        this.properties.put(p.key(), Collections.singletonList(p));
+
+        if(!this.properties.containsKey(p.key())) {
+            this.properties.put(p.key(), new ArrayList());
+        }
+        this.properties.get(p.key()).add(p);
     }
 
     public void internalSetVertex(final DetachedVertex vertex) {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/Gremlin.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/Gremlin.java
index a03789e..63781e0 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/Gremlin.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/Gremlin.java
@@ -30,7 +30,7 @@
 
     static {
         try {
-            version = Manifests.read("version");
+            version = Manifests.read("tinkerpop-version");
         }
         catch (Throwable t) {
             version = "VersionNotFound";
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/GremlinScriptCheckerTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/GremlinScriptCheckerTest.java
index 620ea0e..9287528 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/GremlinScriptCheckerTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/GremlinScriptCheckerTest.java
@@ -35,6 +35,7 @@
         final GremlinScriptChecker.Result r = GremlinScriptChecker.parse("g.with(true).V().out('knows')");
         assertEquals(Optional.empty(), r.getTimeout());
         assertEquals(Optional.empty(), r.getRequestId());
+        assertEquals(Optional.empty(), r.getMaterializeProperties());
     }
 
     @Test
@@ -43,6 +44,7 @@
         assertSame(EMPTY_RESULT, r);
         assertEquals(Optional.empty(), r.getTimeout());
         assertEquals(Optional.empty(), r.getRequestId());
+        assertEquals(Optional.empty(), r.getMaterializeProperties());
     }
 
     @Test
@@ -156,7 +158,7 @@
     public void shouldIdentifyRequestIdAsTokenKeyWithoutClassName() {
         assertEquals("db024fca-ed15-4375-95de-4c6106aef895", GremlinScriptChecker.parse("g.with(REQUEST_ID, \"db024fca-ed15-4375-95de-4c6106aef895\").with(true).V().out('knows')").
                 getRequestId().get());
-        assertEquals("db024fca-ed15-4375-95de-4c6106aef895", GremlinScriptChecker.parse("g.with(REQUEST_ID, \"db024fca-ed15-4375-95de-4c6106aef895\").with(true).V().out('knows')").
+        assertEquals("db024fca-ed15-4375-95de-4c6106aef895", GremlinScriptChecker.parse("g.with(REQUEST_ID, 'db024fca-ed15-4375-95de-4c6106aef895').with(true).V().out('knows')").
                 getRequestId().get());
     }
 
@@ -193,11 +195,56 @@
     }
 
     @Test
+    public void shouldIdentifyMaterializePropertiesSingleQuoted() {
+        assertEquals("all", GremlinScriptChecker.parse("g.with('materializeProperties', 'all').with(true).V().out('knows')").
+                getMaterializeProperties().get());
+        assertEquals("all", GremlinScriptChecker.parse("g.with(\"materializeProperties\", 'all').with(true).V().out('knows')").
+                getMaterializeProperties().get());
+    }
+
+    @Test
+    public void shouldIdentifyMaterializePropertiesDoubleQuoted() {
+        assertEquals("all", GremlinScriptChecker.parse("g.with('materializeProperties', \"all\").with(true).V().out('knows')").
+                getMaterializeProperties().get());
+        assertEquals("all", GremlinScriptChecker.parse("g.with(\"materializeProperties\", \"all\").with(true).V().out('knows')").
+                getMaterializeProperties().get());
+    }
+
+    @Test
+    public void shouldIdentifyMaterializePropertiesWithEmbeddedQuote() {
+        assertEquals("te's\"t", GremlinScriptChecker.parse("g.with('materializeProperties', \"te's\"t\").with(true).V().out('knows')").
+                getMaterializeProperties().get());
+    }
+
+    @Test
+    public void shouldIdentifyMaterializePropertiesAsTokenKeyWithoutClassName() {
+        assertEquals("all", GremlinScriptChecker.parse("g.with(ARGS_MATERIALIZE_PROPERTIES, 'all').with(true).V().out('knows')").
+                getMaterializeProperties().get());
+        assertEquals("all", GremlinScriptChecker.parse("g.with(ARGS_MATERIALIZE_PROPERTIES, \"all\").with(true).V().out('knows')").
+                getMaterializeProperties().get());
+    }
+
+    @Test
+    public void shouldIdentifyMaterializePropertiesAsTokenKey() {
+        assertEquals("all", GremlinScriptChecker.parse("g.with(Tokens.ARGS_MATERIALIZE_PROPERTIES, 'all').with(true).V().out('knows')").
+                getMaterializeProperties().get());
+        assertEquals("all", GremlinScriptChecker.parse("g.with(Tokens.ARGS_MATERIALIZE_PROPERTIES, \"all\").with(true).V().out('knows')").
+                getMaterializeProperties().get());
+    }
+
+    @Test
+    public void shouldIdentifyMultipleMaterializeProperties() {
+        assertEquals("all", GremlinScriptChecker.parse("g.with('materializeProperties', \"hello\").with(\"materializeProperties\", 'world').with('materializeProperties', 'all').with(true).V().out('knows')").
+                getMaterializeProperties().get());
+    }
+
+    @Test
     public void shouldFindAllResults() {
         final GremlinScriptChecker.Result r = GremlinScriptChecker.parse(
-                "g.with('evaluationTimeout', 1000).with(true).with(REQUEST_ID, \"db024fca-ed15-4375-95de-4c6106aef895\").V().out('knows')");
+                "g.with('evaluationTimeout', 1000).with(true).with(REQUEST_ID, \"db024fca-ed15-4375-95de-4c6106aef895\").with(\"materializeProperties\", 'all').V().out('knows')");
         assertEquals(1000, r.getTimeout().get().longValue());
         assertEquals("db024fca-ed15-4375-95de-4c6106aef895", r.getRequestId().get());
+        assertEquals("all", r.getMaterializeProperties().get());
     }
 
     @Test
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/ScriptEngineCacheTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/ScriptEngineCacheTest.java
index 9e6d0dc..8900cd3 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/ScriptEngineCacheTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/jsr223/ScriptEngineCacheTest.java
@@ -18,7 +18,9 @@
  */
 package org.apache.tinkerpop.gremlin.jsr223;
 
+import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertSame;
+import static org.junit.Assume.assumeThat;
 
 import org.apache.tinkerpop.gremlin.AssertHelper;
 import org.junit.Test;
@@ -35,6 +37,9 @@
 
     @Test
     public void shouldGetEngineFromCache() {
+        String javaVersion = System.getProperty("java.version");
+        int majorVersion = Integer.parseInt(javaVersion.substring(0, javaVersion.indexOf('.')));
+        assumeThat("Requires lower than JDK 14.", majorVersion < 14, is(true));
         assertSame(ScriptEngineCache.get("nashorn"), ScriptEngineCache.get("nashorn"));
     }
 
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitorTest.java
index be1af46..d9a4fce 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitorTest.java
@@ -1124,4 +1124,25 @@
         compare(g.V().with("blah", "bleh"),
                 eval("g.V().with('blah', 'bleh')"));
     }
+
+    @Test
+    public void testTraversalMethod_midTraversal_E() throws Exception {
+        compare(g.inject(1).E(), eval("g.inject(1).E()"));
+    }
+
+    @Test
+    public void testTraversalMethod_midTraversal_E_multipleArgs() throws Exception {
+        compare(g.inject(1).E(2,null), eval("g.inject(1).E(2,null)"));
+    }
+
+    @Test
+    public void testTraversalMethod_midTraversal_E_spawning() throws Exception {
+        compare(g.V().coalesce(E(),addE("person")), eval("g.V().coalesce(__.E(),__.addE('person'))"));
+    }
+
+    @Test
+    public void testTraversalMethod_midTraversal_E_multipleArgs_spawning() throws Exception {
+        compare(g.V().coalesce(E(1,2),addE("person")),
+                eval("g.V().coalesce(__.E(1,2),__.addE('person'))"));
+    }
 }
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyTest.java
index c5d4d7e..bacf05b 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/PartitionStrategyTest.java
@@ -50,6 +50,7 @@
 import static org.hamcrest.core.IsInstanceOf.instanceOf;
 import static org.hamcrest.core.IsIterableContaining.hasItem;
 import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.core.IsIterableContaining.hasItem;
 import static org.junit.Assert.assertEquals;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.fail;
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ReferenceElementStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/ReferenceElementStrategyTest.java
similarity index 95%
rename from gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ReferenceElementStrategyTest.java
rename to gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/ReferenceElementStrategyTest.java
index d689972..f718cf5 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/ReferenceElementStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/finalization/ReferenceElementStrategyTest.java
@@ -16,11 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration;
+package org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization;
 
 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.strategy.finalization.ReferenceElementStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GolangTranslatorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GolangTranslatorTest.java
index 19b37b7..81e9559 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GolangTranslatorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GolangTranslatorTest.java
@@ -31,7 +31,6 @@
 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
 import org.apache.tinkerpop.gremlin.util.function.Lambda;
-import org.junit.Ignore;
 import org.junit.Test;
 
 import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal;
diff --git a/gremlin-dotnet/build/generate.groovy b/gremlin-dotnet/build/generate.groovy
index 77659aa..a1c0947 100644
--- a/gremlin-dotnet/build/generate.groovy
+++ b/gremlin-dotnet/build/generate.groovy
@@ -89,7 +89,8 @@
 
     writer.writeLine("\n\n//********************************************************************************")
     writer.writeLine("//* Do NOT edit this file directly - generated by build/generate.groovy")
-    writer.writeLine("//********************************************************************************\n\n")
+    writer.writeLine("//********************************************************************************\n")
+    writer.writeLine("#nullable disable\n")
 
     writer.writeLine('using System;\n' +
                      'using System.Collections.Generic;\n' +
@@ -174,6 +175,7 @@
             '        }\n' +
             '    }\n' +
             '}\n')
+    writer.writeLine("#nullable restore\n")
 }
 
 
diff --git a/gremlin-dotnet/docker-compose.yml b/gremlin-dotnet/docker-compose.yml
index 99464d9..5f2b872 100644
--- a/gremlin-dotnet/docker-compose.yml
+++ b/gremlin-dotnet/docker-compose.yml
@@ -42,6 +42,8 @@
       timeout: 10s
       retries: 30
       start_period: 30s
+    depends_on:
+      - gremlin-socket-server
 
   gremlin-dotnet-integration-tests:
     container_name: gremlin-dotnet-integration-tests
@@ -50,6 +52,7 @@
       - .:/gremlin-dotnet
       - ../gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features:/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features
       - ../docker/gremlin-test-server:/gremlin-dotnet/gremlin-test-server
+      - ../gremlin-tools/gremlin-socket-server/conf:/gremlin-dotnet/gremlin-socket-server/conf/
     environment:
       - DOCKER_ENVIRONMENT=true
       - TEST_TRANSACTIONS=true
@@ -60,3 +63,10 @@
     depends_on:
       gremlin-server-test-dotnet:
         condition: service_healthy
+
+  gremlin-socket-server:
+    container_name: gremlin-socket-server
+    image: tinkerpop/gremlin-socket-server:${GREMLIN_SERVER}
+    ports:
+      - "45943:45943"
+
diff --git a/gremlin-dotnet/pom.xml b/gremlin-dotnet/pom.xml
index 9f7fb7f..b3f2384 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.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-dotnet</artifactId>
     <name>Apache TinkerPop :: Gremlin.Net</name>
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 2384d22..753caa7 100644
--- a/gremlin-dotnet/src/Gremlin.Net.Template/Gremlin.Net.Template.csproj
+++ b/gremlin-dotnet/src/Gremlin.Net.Template/Gremlin.Net.Template.csproj
@@ -20,6 +20,7 @@
   <PropertyGroup>
     <OutputType>Exe</OutputType>
     <TargetFramework>net6.0</TargetFramework>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
 
   <ItemGroup>    
@@ -28,7 +29,7 @@
     <ProjectReference Include="../Gremlin.Net/Gremlin.Net.csproj" />
 
     <!-- do not edit the version directly - maven updates it automatically -->
-    <PackageReference Include="Gremlin.Net" Version="3.6.5-SNAPSHOT" />
+    <PackageReference Include="Gremlin.Net" Version="3.7.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 0d77a34..e11630e 100644
--- a/gremlin-dotnet/src/Gremlin.Net.Template/Gremlin.Net.Template.nuspec
+++ b/gremlin-dotnet/src/Gremlin.Net.Template/Gremlin.Net.Template.nuspec
@@ -5,7 +5,7 @@
         <title>Gremlin.Net Template</title>
 
         <!-- do not edit the version directly - maven updates it automatically -->
-        <version>3.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
 
         <description>Gremlin.Net template to create a console application with dotnet new.</description>
         <authors>Apache TinkerPop</authors>
diff --git a/gremlin-dotnet/src/Gremlin.Net.Template/Service.cs b/gremlin-dotnet/src/Gremlin.Net.Template/Service.cs
index 4ded6d3..d4ba4eb 100644
--- a/gremlin-dotnet/src/Gremlin.Net.Template/Service.cs
+++ b/gremlin-dotnet/src/Gremlin.Net.Template/Service.cs
@@ -35,7 +35,7 @@
             _g = g;
         }
 
-        public IList<string> FindCreatorsOfSoftware(string softwareName)
+        public IList<string?> FindCreatorsOfSoftware(string softwareName)
         {
             return _g.V().HasLabel("software").Has("name", softwareName).In("created").Values<string>("name").ToList();
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Connection.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Connection.cs
index cabe587..913bed2 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Connection.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Connection.cs
@@ -45,9 +45,9 @@
         private readonly IMessageSerializer _messageSerializer;
         private readonly Uri _uri;
         private readonly IWebSocketConnection _webSocketConnection;
-        private readonly string _username;
-        private readonly string _password;
-        private readonly string _sessionId;
+        private readonly string? _username;
+        private readonly string? _password;
+        private readonly string? _sessionId;
         private readonly bool _sessionEnabled;
 
         private readonly ConcurrentQueue<(RequestMessage msg, CancellationToken cancellationToken)> _writeQueue = new();
@@ -60,8 +60,8 @@
         private int _writeInProgress = 0;
         private const int Closed = 1;
 
-        public Connection(IWebSocketConnection webSocketConnection, Uri uri, string username, string password,
-            IMessageSerializer messageSerializer, string sessionId)
+        public Connection(IWebSocketConnection webSocketConnection, Uri uri, string? username, string? password,
+            IMessageSerializer messageSerializer, string? sessionId)
         {
             _uri = uri;
             _username = username;
@@ -131,7 +131,8 @@
             var receivedMsg = await _messageSerializer.DeserializeMessageAsync(received).ConfigureAwait(false);
             if (receivedMsg == null)
             {
-                ThrowMessageDeserializedNull();
+                throw new InvalidOperationException(
+                    "Received data deserialized into null object message. Cannot operate on it.");
             }
 
             try
@@ -155,9 +156,6 @@
             }
         }
 
-        private static void ThrowMessageDeserializedNull() =>
-            throw new InvalidOperationException("Received data deserialized into null object message. Cannot operate on it.");
-
         private void HandleReceivedMessage(ResponseMessage<List<object>> receivedMsg)
         {
             var status = receivedMsg.Status;
@@ -302,7 +300,7 @@
             {
                 msgBuilder.AddArgument(kv.Key, kv.Value);
             }
-            msgBuilder.AddArgument(Tokens.ArgsSession, _sessionId);
+            msgBuilder.AddArgument(Tokens.ArgsSession, _sessionId!);
             return msgBuilder.Create();
         }
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/ConnectionFactory.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/ConnectionFactory.cs
index 3ccbc3c..4657172 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/ConnectionFactory.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/ConnectionFactory.cs
@@ -27,11 +27,11 @@
     {
         private readonly WebSocketSettings _webSocketSettings;
         private readonly GremlinServer _gremlinServer;
-        private readonly string _sessionId;
+        private readonly string? _sessionId;
         private readonly IMessageSerializer _messageSerializer;
 
         public ConnectionFactory(GremlinServer gremlinServer, IMessageSerializer messageSerializer,
-            WebSocketSettings webSocketSettings, string sessionId)
+            WebSocketSettings webSocketSettings, string? sessionId)
         {
             _gremlinServer = gremlinServer;
             _messageSerializer = messageSerializer;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Exceptions/ConnectionClosedException.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Exceptions/ConnectionClosedException.cs
index 13417ea..e03c7f6 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Exceptions/ConnectionClosedException.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Exceptions/ConnectionClosedException.cs
@@ -27,8 +27,8 @@
 namespace Gremlin.Net.Driver.Exceptions
 {
     /// <summary>
-    ///     The exception that is thrown for requests that in-flight when the underlyingg websocket is closed by the server.
-    ///     Requests that recieve this exception will be in a non-deteministic state and may need to be retried.
+    ///     The exception that is thrown for requests that in-flight when the underlying websocket is closed by the server.
+    ///     Requests that receive this exception will be in a non-deterministic state and may need to be retried.
     /// </summary>
     /// <remarks>
     ///     It is recommended to use the same request retry policy that is applied when a <see cref="System.Net.WebSockets.WebSocketException" />,
@@ -44,19 +44,19 @@
         /// <summary>
         ///     Gets the Websocket closure description provided by the server.
         /// </summary>
-        public string Description { get; }
+        public string? Description { get; }
 
         /// <summary>
         ///     Initializes a new instance of the <see cref="ConnectionClosedException" /> class.
         /// </summary>
-        public ConnectionClosedException(WebSocketCloseStatus? status, string description)
+        public ConnectionClosedException(WebSocketCloseStatus? status, string? description)
             : base(CreateMessage(status, description))
         {
             Status = status;
             Description = description;
         }
 
-        private static string CreateMessage(WebSocketCloseStatus? status, string description)
+        private static string CreateMessage(WebSocketCloseStatus? status, string? description)
         {
             return $"Connection closed by server. CloseStatus: {status?.ToString() ?? "<none>"}, CloseDescription: {description ?? "<none>"}." +
                 " Any in-progress requests on the connection will be in an unknown state, and may need to be retried.";
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClient.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClient.cs
index 361cf57..e97d8eb 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClient.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClient.cs
@@ -57,8 +57,8 @@
         /// <param name="sessionId">The session Id if Gremlin Client in session mode, defaults to null as session-less Client.</param>
         [Obsolete("This constructor is obsolete. Use the constructor that takes a IMessageSerializer instead.")]
         public GremlinClient(GremlinServer gremlinServer, GraphSONReader graphSONReader, GraphSONWriter graphSONWriter,
-            ConnectionPoolSettings connectionPoolSettings = null,
-            Action<ClientWebSocketOptions> webSocketConfiguration = null, string sessionId = null)
+            ConnectionPoolSettings? connectionPoolSettings = null,
+            Action<ClientWebSocketOptions>? webSocketConfiguration = null, string? sessionId = null)
             : this(gremlinServer, graphSONReader, graphSONWriter, SerializationTokens.GraphSON3MimeType,
                 connectionPoolSettings, webSocketConfiguration, sessionId)
         {
@@ -78,9 +78,9 @@
         /// </param>
         /// <param name="sessionId">The session Id if Gremlin Client in session mode, defaults to null as session-less Client.</param>
         [Obsolete("This constructor is obsolete. Use the constructor that takes a IMessageSerializer instead.")]
-        public GremlinClient(GremlinServer gremlinServer, GraphSONReader graphSONReader, GraphSONWriter graphSONWriter,
-            string mimeType, ConnectionPoolSettings connectionPoolSettings = null,
-            Action<ClientWebSocketOptions> webSocketConfiguration = null, string sessionId = null)
+        public GremlinClient(GremlinServer gremlinServer, GraphSONReader? graphSONReader, GraphSONWriter? graphSONWriter,
+            string mimeType, ConnectionPoolSettings? connectionPoolSettings = null,
+            Action<ClientWebSocketOptions>? webSocketConfiguration = null, string? sessionId = null)
         {
             IMessageSerializer messageSerializer;
             switch (mimeType)
@@ -91,8 +91,8 @@
                     VerifyGraphSONArgumentTypeForMimeType<GraphSON3Writer>(graphSONWriter, nameof(graphSONWriter),
                         mimeType);
                     messageSerializer = new GraphSON3MessageSerializer(
-                        (GraphSON3Reader) graphSONReader ?? new GraphSON3Reader(),
-                        (GraphSON3Writer) graphSONWriter ?? new GraphSON3Writer());
+                        (GraphSON3Reader?) graphSONReader ?? new GraphSON3Reader(),
+                        (GraphSON3Writer?) graphSONWriter ?? new GraphSON3Writer());
                     break;
                 case SerializationTokens.GraphSON2MimeType:
                     VerifyGraphSONArgumentTypeForMimeType<GraphSON2Reader>(graphSONReader, nameof(graphSONReader),
@@ -100,8 +100,8 @@
                     VerifyGraphSONArgumentTypeForMimeType<GraphSON2Writer>(graphSONWriter, nameof(graphSONWriter),
                         mimeType);
                     messageSerializer = new GraphSON2MessageSerializer(
-                        (GraphSON2Reader) graphSONReader ?? new GraphSON2Reader(),
-                        (GraphSON2Writer) graphSONWriter ?? new GraphSON2Writer());
+                        (GraphSON2Reader?) graphSONReader ?? new GraphSON2Reader(),
+                        (GraphSON2Writer?) graphSONWriter ?? new GraphSON2Writer());
                     break;
                 default:
                     throw new ArgumentException(nameof(mimeType), $"{mimeType} not supported");
@@ -135,10 +135,10 @@
                 connectionPoolSettings ?? new ConnectionPoolSettings(), LoggerFactory.CreateLogger<ConnectionPool>());
         }
 
-        private static void VerifyGraphSONArgumentTypeForMimeType<T>(object argument, string argumentName,
+        private static void VerifyGraphSONArgumentTypeForMimeType<T>(object? argument, string argumentName,
             string mimeType)
         {
-            if (argument != null && !(argument is T))
+            if (argument != null && argument is not T)
             {
                 throw new ArgumentException(
                     $"{argumentName} is not a {typeof(T).Name} but the mime type is: {mimeType}", argumentName);
@@ -168,10 +168,10 @@
         ///     that could potentially be controlled by an untrusted user.
         /// </param>
         /// <param name="loggerFactory">A factory to create loggers. If not provided, then nothing will be logged.</param>
-        public GremlinClient(GremlinServer gremlinServer, IMessageSerializer messageSerializer = null,
-            ConnectionPoolSettings connectionPoolSettings = null,
-            Action<ClientWebSocketOptions> webSocketConfiguration = null, string sessionId = null,
-            bool disableCompression = false, ILoggerFactory loggerFactory = null)
+        public GremlinClient(GremlinServer gremlinServer, IMessageSerializer? messageSerializer = null,
+            ConnectionPoolSettings? connectionPoolSettings = null,
+            Action<ClientWebSocketOptions>? webSocketConfiguration = null, string? sessionId = null,
+            bool disableCompression = false, ILoggerFactory? loggerFactory = null)
         {
             messageSerializer ??= new GraphBinaryMessageSerializer();
             var webSocketSettings = new WebSocketSettings
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClientExtensions.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClientExtensions.cs
index 54dabff..8132c7a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClientExtensions.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClientExtensions.cs
@@ -52,9 +52,9 @@
         ///     Thrown when a response is received from Gremlin Server that indicates
         ///     that an error occurred.
         /// </exception>
-        public static async Task<T> SubmitWithSingleResultAsync<T>(this IGremlinClient gremlinClient,
+        public static async Task<T?> SubmitWithSingleResultAsync<T>(this IGremlinClient gremlinClient,
             string requestScript,
-            Dictionary<string, object> bindings = null,
+            Dictionary<string, object>? bindings = null,
             CancellationToken cancellationToken = default)
         {
             var resultCollection = await gremlinClient.SubmitAsync<T>(requestScript, bindings, cancellationToken)
@@ -78,7 +78,7 @@
         ///     Thrown when a response is received from Gremlin Server that indicates
         ///     that an error occurred.
         /// </exception>
-        public static async Task<T> SubmitWithSingleResultAsync<T>(this IGremlinClient gremlinClient,
+        public static async Task<T?> SubmitWithSingleResultAsync<T>(this IGremlinClient gremlinClient,
             RequestMessage requestMessage, CancellationToken cancellationToken = default)
         {
             var resultCollection =
@@ -100,7 +100,7 @@
         ///     that an error occurred.
         /// </exception>
         public static async Task SubmitAsync(this IGremlinClient gremlinClient, string requestScript,
-            Dictionary<string, object> bindings = null, CancellationToken cancellationToken = default)
+            Dictionary<string, object>? bindings = null, CancellationToken cancellationToken = default)
         {
             await gremlinClient.SubmitAsync<object>(requestScript, bindings, cancellationToken).ConfigureAwait(false);
         }
@@ -138,7 +138,7 @@
         /// </exception>
         public static async Task<ResultSet<T>> SubmitAsync<T>(this IGremlinClient gremlinClient,
             string requestScript,
-            Dictionary<string, object> bindings = null,
+            Dictionary<string, object>? bindings = null,
             CancellationToken cancellationToken = default)
         {
             var msgBuilder = RequestMessage.Build(Tokens.OpsEval).AddArgument(Tokens.ArgsGremlin, requestScript);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinServer.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinServer.cs
index 43ef159..fbe5bae 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinServer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinServer.cs
@@ -39,7 +39,7 @@
         /// <param name="username">The username to submit on requests that require authentication.</param>
         /// <param name="password">The password to submit on requests that require authentication.</param>
         public GremlinServer(string hostname = "localhost", int port = 8182, bool enableSsl = false,
-            string username = null, string password = null)
+            string? username = null, string? password = null)
         {
             Uri = CreateUri(hostname, port, enableSsl);
             Username = username;
@@ -55,12 +55,12 @@
         /// <summary>
         ///     Gets the username to submit on requests that require authentication.
         /// </summary>
-        public string Username { get; }
+        public string? Username { get; }
 
         /// <summary>
         ///     Gets the password to submit on requests that require authentication.
         /// </summary>
-        public string Password { get; }
+        public string? Password { get; }
 
         private Uri CreateUri(string hostname, int port, bool enableSsl)
         {
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/IMessageSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/IMessageSerializer.cs
index e1a6a0e..0f2d79f 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/IMessageSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/IMessageSerializer.cs
@@ -48,7 +48,7 @@
         /// <param name="message">The serialized message to deserialize.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <returns>The deserialized <see cref="ResponseMessage{T}"/>.</returns>
-        Task<ResponseMessage<List<object>>> DeserializeMessageAsync(byte[] message,
+        Task<ResponseMessage<List<object>>?> DeserializeMessageAsync(byte[] message,
             CancellationToken cancellationToken = default);
     }
 }
\ 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 a273cc0..bbb4c16 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseMessage.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseMessage.cs
@@ -29,20 +29,33 @@
     ///     The message returned from the server.
     /// </summary>
     /// <typeparam name="T">The type of the data returned.</typeparam>
-    public class ResponseMessage<T>
+    public record ResponseMessage<T>
     {
         /// <summary>
-        ///     Gets or sets the identifier of the <see cref="RequestMessage"/> that generated this <see cref="ResponseMessage{T}"/>.
+        ///     Initializes a new instance of the <see cref="ResponseMessage{T}" /> record.
         /// </summary>
-        public Guid? RequestId { get; set; }
+        /// <param name="requestId">The identifier of the <see cref="RequestMessage"/> that generated this <see cref="ResponseMessage{T}"/>.</param>
+        /// <param name="status">Status information about this <see cref="ResponseMessage{T}"/>.</param>
+        /// <param name="result">The result with its data and optional meta information.</param>
+        public ResponseMessage(Guid? requestId, ResponseStatus status, ResponseResult<T> result)
+        {
+            RequestId = requestId;
+            Status = status;
+            Result = result;
+        }
+        
+        /// <summary>
+        ///     Gets the identifier of the <see cref="RequestMessage"/> that generated this <see cref="ResponseMessage{T}"/>.
+        /// </summary>
+        public Guid? RequestId { get; }
 
         /// <summary>
-        ///     Gets or sets status information about this <see cref="ResponseMessage{T}"/>.
+        ///     Gets status information about this <see cref="ResponseMessage{T}"/>.
         /// </summary>
-        public ResponseStatus Status { get; set; }
+        public ResponseStatus Status { get; }
 
         /// <summary>
-        ///     Gets or sets the result with its data and optional meta information.
+        ///     Gets the result with its data and optional meta information.
         /// </summary>
         public ResponseResult<T> Result { get; set; }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseResult.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseResult.cs
index abc2907..387893a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseResult.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseResult.cs
@@ -30,16 +30,27 @@
     ///     <see cref="ResponseMessage{T}"/> by the server.
     /// </summary>
     /// <typeparam name="T">The type of the <see cref="Data"/>.</typeparam>
-    public class ResponseResult<T>
+    public record ResponseResult<T>
     {
         /// <summary>
-        ///     Gets or sets the data of this result.
+        /// Initializes a new instance of the <see cref="ResponseResult{T}" /> record.
         /// </summary>
-        public T Data { get; set; }
+        /// <param name="data">The data of this result.</param>
+        /// <param name="meta">The (optional) meta data of this result.</param>
+        public ResponseResult(T? data, Dictionary<string, object>? meta = null)
+        {
+            Data = data;
+            Meta = meta ?? new Dictionary<string, object>();
+        }
+        
+        /// <summary>
+        ///     Gets the data of this result.
+        /// </summary>
+        public T? Data { get; }
 
         /// <summary>
-        ///     Gets or sets meta data of this result.
+        ///     Gets meta data of this result.
         /// </summary>
-        public Dictionary<string, object> Meta { get; set; }
+        public Dictionary<string, object> Meta { get; }
     }
 }
\ 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 63530a3..1d36113 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseStatus.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/ResponseStatus.cs
@@ -29,22 +29,36 @@
     /// <summary>
     ///     Represents status information of a <see cref="ResponseMessage{T}"/>.
     /// </summary>
-    public class ResponseStatus
+    public record ResponseStatus
     {
         /// <summary>
-        ///     Gets or sets the <see cref="ResponseStatusCode"/>.
+        ///     Initializes a new instance of the <see cref="ResponseStatus" /> record.
         /// </summary>
-        public ResponseStatusCode Code { get; set; }
+        /// <param name="code">The <see cref="ResponseStatusCode" />.</param>
+        /// <param name="attributes">The (optional) attributes with protocol-level information.</param>
+        /// <param name="message">The (optional) message which is just a human-readable string usually associated with errors.</param>
+        public ResponseStatus(ResponseStatusCode code, Dictionary<string, object>? attributes = null,
+            string? message = null)
+        {
+            Code = code;
+            Attributes = attributes ?? new Dictionary<string, object>();
+            Message = message;
+        }
+        
+        /// <summary>
+        ///     Gets the <see cref="ResponseStatusCode"/>.
+        /// </summary>
+        public ResponseStatusCode Code { get; }
 
         /// <summary>
-        ///     Gets or sets the attributes <see cref="Dictionary{TKey,TValue}"/> with protocol-level information.
+        ///     Gets the attributes <see cref="Dictionary{TKey,TValue}"/> with protocol-level information.
         /// </summary>
-        public Dictionary<string, object> Attributes { get; set; }
+        public Dictionary<string, object> Attributes { get; }
 
         /// <summary>
-        ///     Gets or sets the message which is just a human-readable string usually associated with errors.
+        ///     Gets the message which is just a human-readable string usually associated with errors.
         /// </summary>
-        public string Message { get; set; }
+        public string? Message { get; }
     }
 
     internal static class ResponseStatusExtensions
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs
index a623a44..b9e0aa0 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs
@@ -51,10 +51,10 @@
         private readonly List<string> _allowedKeys = new()
         {
             Tokens.ArgsEvalTimeout, "scriptEvaluationTimeout", Tokens.ArgsBatchSize,
-            Tokens.RequestId, Tokens.ArgsUserAgent
+            Tokens.RequestId, Tokens.ArgsUserAgent, Tokens.ArgMaterializeProperties
         };
 
-        private readonly string _sessionId;
+        private readonly string? _sessionId;
         private string Processor => IsSessionBound ? Tokens.ProcessorSession : Tokens.ProcessorTraversal;
 
         /// <inheritdoc />
@@ -69,7 +69,7 @@
         /// <param name="loggerFactory">A factory to create loggers. If not provided, then nothing will be logged.</param>
         /// <exception cref="ArgumentNullException">Thrown when client is null.</exception>
         public DriverRemoteConnection(string host, int port, string traversalSource = "g",
-            ILoggerFactory loggerFactory = null) : this(
+            ILoggerFactory? loggerFactory = null) : this(
             new GremlinClient(new GremlinServer(host, port), loggerFactory: loggerFactory), traversalSource,
             logger: loggerFactory?.CreateLogger<DriverRemoteConnection>() ?? NullLogger<DriverRemoteConnection>.Instance)
         {
@@ -86,8 +86,8 @@
         {
         }
 
-        private DriverRemoteConnection(IGremlinClient client, string traversalSource, string sessionId = null,
-            ILogger<DriverRemoteConnection> logger = null)
+        private DriverRemoteConnection(IGremlinClient client, string traversalSource, string? sessionId = null,
+            ILogger<DriverRemoteConnection>? logger = null)
         {
             _client = client ?? throw new ArgumentNullException(nameof(client));
             _traversalSource = traversalSource ?? throw new ArgumentNullException(nameof(traversalSource));
@@ -110,12 +110,12 @@
         /// <param name="bytecode">The <see cref="Bytecode" /> to submit.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <returns>A <see cref="ITraversal" /> allowing to access the results and side-effects.</returns>
-        public async Task<ITraversal<S, E>> SubmitAsync<S, E>(Bytecode bytecode,
+        public async Task<ITraversal<TStart, TEnd>> SubmitAsync<TStart, TEnd>(Bytecode bytecode,
             CancellationToken cancellationToken = default)
         {
             var requestId = Guid.NewGuid();
             var resultSet = await SubmitBytecodeAsync(requestId, bytecode, cancellationToken).ConfigureAwait(false);
-            return new DriverRemoteTraversal<S, E>(_client, requestId, resultSet);
+            return new DriverRemoteTraversal<TStart, TEnd>(resultSet);
         }
 
         private async Task<IEnumerable<Traverser>> SubmitBytecodeAsync(Guid requestid, Bytecode bytecode,
@@ -132,15 +132,15 @@
 
             if (IsSessionBound)
             {
-                requestMsg.AddArgument(Tokens.ArgsSession, _sessionId);
+                requestMsg.AddArgument(Tokens.ArgsSession, _sessionId!);
             }
 
             var optionsStrategyInst = bytecode.SourceInstructions.Find(
                 s => s.OperatorName == "withStrategies" && s.Arguments[0] is OptionsStrategy);
             if (optionsStrategyInst != null)
             {
-                OptionsStrategy optionsStrategy = optionsStrategyInst.Arguments[0];
-                foreach (KeyValuePair<string,dynamic> pair in optionsStrategy.Configuration)
+                OptionsStrategy optionsStrategy = optionsStrategyInst.Arguments[0]!;
+                foreach (var pair in optionsStrategy.Configuration)
                 {
                     if (_allowedKeys.Contains(pair.Key))
                     {
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteTraversal.cs
index cf50646..66501ff 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteTraversal.cs
@@ -27,12 +27,13 @@
 
 namespace Gremlin.Net.Driver.Remote
 {
-    internal class DriverRemoteTraversal<S, E> : DefaultTraversal<S, E>
+    internal class DriverRemoteTraversal<TStart, TEnd> : DefaultTraversal<TStart, TEnd>
     {
-        public DriverRemoteTraversal(IGremlinClient gremlinClient, Guid requestId,
-            IEnumerable<Traverser> traversers)
+        public DriverRemoteTraversal(IEnumerable<Traverser> traversers)
         {
             Traversers = traversers;
         }
+
+        public override Bytecode Bytecode => throw new NotSupportedException("Remote traversals do not have Bytecode");
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/ResponseHandlerForSingleRequestMessage.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/ResponseHandlerForSingleRequestMessage.cs
index 93b3097..7993ccb 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/ResponseHandlerForSingleRequestMessage.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/ResponseHandlerForSingleRequestMessage.cs
@@ -33,13 +33,13 @@
         public Task<ResultSet<T>> Result => _tcs.Task;
 
         private readonly TaskCompletionSource<ResultSet<T>> _tcs =
-            new TaskCompletionSource<ResultSet<T>>(TaskCreationOptions.RunContinuationsAsynchronously);
+            new(TaskCreationOptions.RunContinuationsAsynchronously);
         
-        private readonly List<T> _result = new List<T>();
+        private readonly List<T> _result = new();
 
         public void HandleReceived(ResponseMessage<List<object>> received)
         {
-            foreach (var d in received.Result.Data)
+            foreach (var d in received.Result.Data!)
             {
                 _result.Add((T) d);
             }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs
index 2e2817a..8a4e9ba 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs
@@ -33,87 +33,93 @@
         /// <summary>
         ///     The key for the unique identifier of the request.
         /// </summary>
-        public static string RequestId = "requestId";
+        public const string RequestId = "requestId";
 
         /// <summary>
         ///     Operation used by the client to authenticate itself.
         /// </summary>
-        public static string OpsAuthentication = "authentication";
+        public const string OpsAuthentication = "authentication";
 
         /// <summary>
         ///     Operation used for a request that contains the Bytecode representation of a Traversal.
         /// </summary>
-        public static string OpsBytecode = "bytecode";
+        public const string OpsBytecode = "bytecode";
 
         /// <summary>
         ///     Operation used to evaluate a Gremlin script provided as a string.
         /// </summary>
-        public static string OpsEval = "eval";
+        public const string OpsEval = "eval";
 
         /// <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";
+        public const string OpsClose = "close";
 
         /// <summary>
         ///     Default OpProcessor.
         /// </summary>
-        public static string ProcessorTraversal = "traversal";
+        public const string ProcessorTraversal = "traversal";
 
         /// <summary>
         ///     Session OpProcessor.
         /// </summary>
-        public static string ProcessorSession = "session";
+        public const string ProcessorSession = "session";
 
         /// <summary>
         ///     Argument name that allows the definition of the number of items each ResponseMessage should
         ///     contain from a particular result - overrides the resultIterationBatchSize server setting.
         /// </summary>
-        public static string ArgsBatchSize = "batchSize";
+        public const string ArgsBatchSize = "batchSize";
 
         /// <summary>
         ///     Argument name that allows definition of a map of key/value pairs to apply as variables in the
         ///     context of the Gremlin request sent to the server.
         /// </summary>
-        public static string ArgsBindings = "bindings";
+        public const string ArgsBindings = "bindings";
 
         /// <summary>
         ///     Argument name that allows definition of alias names for Graph and TraversalSource objects on the
         ///     remote system.
         /// </summary>
-        public static string ArgsAliases = "aliases";
+        public const string ArgsAliases = "aliases";
 
         /// <summary>
         ///     Argument name that corresponds to the Gremlin to evaluate.
         /// </summary>
-        public static string ArgsGremlin = "gremlin";
+        public const string ArgsGremlin = "gremlin";
 
         /// <summary>
         ///     Argument name that allows to define the id of session.
         /// </summary>
-        public static string ArgsSession = "session";
+        public const string ArgsSession = "session";
 
         /// <summary>
         ///     Argument name that allows a value that is a custom string that the user can pass to a server that
         ///     might accept it for purpose of identifying the kind of client it came from.
         /// </summary>
-        public static string ArgsUserAgent = "userAgent";
+        public const string ArgsUserAgent = "userAgent";
 
         /// <summary>
         ///     Argument name that allows definition of the flavor of Gremlin used (e.g. gremlin-groovy) to process the request.
         /// </summary>
-        public static string ArgsLanguage = "language";
+        public const string ArgsLanguage = "language";
 
         /// <summary>
         ///     Argument name that allows the override of the server setting that determines the maximum time to wait for a
         ///     request to execute on the server.
         /// </summary>
-        public static string ArgsEvalTimeout = "evaluationTimeout";
+        public const string ArgsEvalTimeout = "evaluationTimeout";
+
+        /// <summary>
+        ///     Argument name that allows the override of handling properties.
+        ///     Allowed values: all, tokens
+        /// </summary>
+        public const string ArgMaterializeProperties = "materializeProperties";
 
         /// <summary>
         ///     Argument name for the response to the server authentication challenge. This value is dependent on the SASL
         ///     authentication mechanism required by the server.
         /// </summary>
-        public static string ArgsSasl = "sasl";
+        public const string ArgsSasl = "sasl";
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketConnection.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketConnection.cs
index 0a5bee9..68fe913 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketConnection.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketConnection.cs
@@ -124,7 +124,7 @@
                     throw new ConnectionClosedException(received.CloseStatus, received.CloseStatusDescription);
                 }
 
-                ms.Write(receiveBuffer.Array, receiveBuffer.Offset, received.Count);
+                ms.Write(receiveBuffer.Array!, receiveBuffer.Offset, received.Count);
             } while (!received.EndOfMessage);
 
             return ms.ToArray();
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketSettings.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketSettings.cs
index 7cb794e..62c8ca0 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketSettings.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketSettings.cs
@@ -39,7 +39,7 @@
         ///     Gets or sets the delegate that will be invoked with the <see cref="ClientWebSocketOptions" />

         ///     object used to configure WebSocket connections.

         /// </summary>

-        public Action<ClientWebSocketOptions> WebSocketConfigurationCallback { get; set; }

+        public Action<ClientWebSocketOptions>? WebSocketConfigurationCallback { get; set; }

 

         public bool EnableUserAgentOnConnect { get; set; }

 

diff --git a/gremlin-dotnet/src/Gremlin.Net/Gremlin.Net.csproj b/gremlin-dotnet/src/Gremlin.Net/Gremlin.Net.csproj
index a89f491..f4461ba 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Gremlin.Net.csproj
+++ b/gremlin-dotnet/src/Gremlin.Net/Gremlin.Net.csproj
@@ -22,11 +22,12 @@
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <LangVersion>9</LangVersion>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
 
   <PropertyGroup Label="Package">
     <!-- do not edit the version directly - maven updates it automatically -->
-    <Version>3.6.5-SNAPSHOT</Version>
+    <Version>3.7.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.
@@ -79,6 +80,10 @@
     
   <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
     <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
+    <PackageReference Include="Nullable" Version="1.3.1">
+      <PrivateAssets>all</PrivateAssets>
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+    </PackageReference>
   </ItemGroup>
 
   <ItemGroup>
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Remote/IRemoteConnection.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Remote/IRemoteConnection.cs
index cf236af..b721e40 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Remote/IRemoteConnection.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Remote/IRemoteConnection.cs
@@ -39,7 +39,7 @@
         /// <param name="bytecode">The <see cref="Bytecode" /> to send.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <returns>The <see cref="ITraversal" /> with the results and optional side-effects.</returns>
-        Task<ITraversal<S, E>> SubmitAsync<S, E>(Bytecode bytecode, CancellationToken cancellationToken = default);
+        Task<ITraversal<TStart, TEnd>> SubmitAsync<TStart, TEnd>(Bytecode bytecode, CancellationToken cancellationToken = default);
 
         /// <summary>
         ///     Creates a <see cref="RemoteTransaction" /> in the context of a <see cref="GraphTraversalSource" /> designed to work with
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Remote/RemoteStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Remote/RemoteStrategy.cs
index d84dba1..aa39f59 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Remote/RemoteStrategy.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Remote/RemoteStrategy.cs
@@ -45,16 +45,16 @@
         }
 
         /// <inheritdoc />
-        public void Apply<S, E>(ITraversal<S, E> traversal)
+        public void Apply<TStart, TEnd>(ITraversal<TStart, TEnd> traversal)
         {
             ApplyAsync(traversal, CancellationToken.None).WaitUnwrap();
         }
 
         /// <inheritdoc />
-        public async Task ApplyAsync<S, E>(ITraversal<S, E> traversal, CancellationToken cancellationToken = default)
+        public async Task ApplyAsync<TStart, TEnd>(ITraversal<TStart, TEnd> traversal, CancellationToken cancellationToken = default)
         {
             if (traversal.Traversers != null) return;
-            var remoteTraversal = await _remoteConnection.SubmitAsync<S, E>(traversal.Bytecode, cancellationToken)
+            var remoteTraversal = await _remoteConnection.SubmitAsync<TStart, TEnd>(traversal.Bytecode, cancellationToken)
                 .ConfigureAwait(false);
             traversal.Traversers = remoteTraversal.Traversers;
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Binding.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Binding.cs
index 80c8269..ce76181 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Binding.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Binding.cs
@@ -35,7 +35,7 @@
         /// </summary>
         /// <param name="key">The key that identifies the <see cref="Binding" />.</param>
         /// <param name="value">The value of the <see cref="Binding" />.</param>
-        public Binding(string key, object value)
+        public Binding(string key, object? value)
         {
             Key = key;
             Value = value;
@@ -49,18 +49,18 @@
         /// <summary>
         ///     Gets the value of the <see cref="Binding" />.
         /// </summary>
-        public object Value { get; }
+        public object? Value { get; }
 
         /// <inheritdoc />
-        public bool Equals(Binding other)
+        public bool Equals(Binding? other)
         {
             if (other == null)
                 return false;
-            return Key == other.Key && Value.Equals(other.Value);
+            return Key == other.Key && (Value?.Equals(other.Value) ?? other.Value == null);
         }
 
         /// <inheritdoc />
-        public override bool Equals(object other)
+        public override bool Equals(object? other)
         {
             if (ReferenceEquals(null, other)) return false;
             if (ReferenceEquals(this, other)) return true;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bindings.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bindings.cs
index a6e13b9..746b499 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bindings.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bindings.cs
@@ -34,10 +34,9 @@
         /// <summary>
         ///     Gets an instance of the <see cref="Bindings" /> class.
         /// </summary>
-        public static Bindings Instance { get; } = new Bindings();
+        public static Bindings Instance { get; } = new();
 
-        private static readonly ThreadLocal<Dictionary<object, string>> BoundVariableByValue =
-            new ThreadLocal<Dictionary<object, string>>();
+        private static readonly ThreadLocal<Dictionary<object, string>> BoundVariableByValue = new();
 
         /// <summary>
         ///     Binds the variable to the specified value.
@@ -45,7 +44,7 @@
         /// <param name="variable">The variable to bind.</param>
         /// <param name="value">The value to which the variable should be bound.</param>
         /// <returns>The bound value.</returns>
-        public TV Of<TV>(string variable, TV value)
+        public TV Of<TV>(string variable, TV value) where TV : notnull
         {
             var dict = BoundVariableByValue.Value;
             if (dict == null)
@@ -57,7 +56,7 @@
             return value;
         }
 
-        internal static string GetBoundVariable<TV>(TV value)
+        internal static string? GetBoundVariable<TV>(TV value) where TV : notnull
         {
             var dict = BoundVariableByValue.Value;
             if (dict == null)
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bytecode.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bytecode.cs
index e692ed2..604ba67 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bytecode.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Bytecode.cs
@@ -24,6 +24,7 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 
 namespace Gremlin.Net.Process.Traversal
@@ -60,19 +61,19 @@
         /// <summary>
         ///     Gets the traversal source instructions.
         /// </summary>
-        public List<Instruction> SourceInstructions { get; } = new List<Instruction>();
+        public List<Instruction> SourceInstructions { get; } = new();
 
         /// <summary>
         ///     Gets the <see cref="ITraversal" /> instructions.
         /// </summary>
-        public List<Instruction> StepInstructions { get; } = new List<Instruction>();
+        public List<Instruction> StepInstructions { get; } = new();
 
         /// <summary>
         ///     Add a traversal source instruction to the bytecode.
         /// </summary>
         /// <param name="sourceName">The traversal source method name (e.g. withSack()).</param>
         /// <param name="args">The traversal source method arguments.</param>
-        public void AddSource(string sourceName, params object[] args)
+        public void AddSource(string sourceName, params object?[] args)
         {
             SourceInstructions.Add(new Instruction(sourceName, FlattenArguments(args)));
             Bindings.Clear();
@@ -83,17 +84,17 @@
         /// </summary>
         /// <param name="stepName">The traversal method name (e.g. out()).</param>
         /// <param name="args">The traversal method arguments.</param>
-        public void AddStep(string stepName, params object[] args)
+        public void AddStep(string stepName, params object?[] args)
         {
             StepInstructions.Add(new Instruction(stepName, FlattenArguments(args)));
             Bindings.Clear();
         }
 
-        private object[] FlattenArguments(object[] arguments)
+        private object?[] FlattenArguments(object?[] arguments)
         {
             if (arguments.Length == 0)
                 return EmptyArray;
-            var flatArguments = new List<object>();
+            var flatArguments = new List<object?>();
             foreach (var arg in arguments)
             {
                 if (arg is object[] objects)
@@ -108,7 +109,8 @@
             return flatArguments.ToArray();
         }
 
-        private object ConvertArgument(object argument, bool searchBindings)
+        [return: NotNullIfNotNull("argument")]
+        private object? ConvertArgument(object? argument, bool searchBindings)
         {
             if (null == argument)
             {
@@ -129,7 +131,7 @@
             
             if (IsDictionaryType(argument.GetType()))
             {
-                var dict = new Dictionary<object, object>();
+                var dict = new Dictionary<object, object?>();
                 foreach (DictionaryEntry item in (IDictionary)argument)
                 {
                     dict[ConvertArgument(item.Key, true)] = ConvertArgument(item.Value, true);
@@ -138,13 +140,13 @@
             }
             if (IsListType(argument.GetType()))
             {
-                var list = new List<object>(((IList) argument).Count);
-                list.AddRange(from object item in (IList) argument select ConvertArgument(item, true));
+                var list = new List<object?>(((IList) argument).Count);
+                list.AddRange(from object? item in (IList)argument select ConvertArgument(item, true));
                 return list;
             }
             if (IsHashSetType(argument.GetType()))
             {
-                var set = new HashSet<object>();
+                var set = new HashSet<object?>();
                 foreach (var item in (IEnumerable)argument)
                 {
                     set.Add(ConvertArgument(item, true));
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/DefaultTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/DefaultTraversal.cs
index 191b7a8..d2da68e 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/DefaultTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/DefaultTraversal.cs
@@ -24,6 +24,7 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 using System.Threading;
 using System.Threading.Tasks;
@@ -33,14 +34,14 @@
     /// <summary>
     ///     A traversal represents a directed walk over a graph.
     /// </summary>
-    public abstract class DefaultTraversal<S, E> : ITraversal<S, E>
+    public abstract class DefaultTraversal<TStart, TEnd> : ITraversal<TStart, TEnd>
     {
-        private IEnumerator<Traverser> _traverserEnumerator;
+        private IEnumerator<Traverser>? _traverserEnumerator;
 
         /// <summary>
         ///     Gets the <see cref="Traversal.Bytecode" /> representation of this traversal.
         /// </summary>
-        public Bytecode Bytecode { get; protected set; }
+        public abstract Bytecode Bytecode { get; }
         
         /// <summary>
         ///     Determines if this traversal was spawned anonymously or not.
@@ -50,7 +51,7 @@
         /// <summary>
         ///     Gets or sets the <see cref="Traverser" />'s of this traversal that hold the results of the traversal.
         /// </summary>
-        public IEnumerable<Traverser> Traversers { get; set; }
+        public IEnumerable<Traverser>? Traversers { get; set; }
 
         ITraversal ITraversal.Iterate()
         {
@@ -63,7 +64,7 @@
         protected ICollection<ITraversalStrategy> TraversalStrategies { get; set; } = new List<ITraversalStrategy>();
 
         private IEnumerator<Traverser> TraverserEnumerator
-            => _traverserEnumerator ?? (_traverserEnumerator = GetTraverserEnumerator());
+            => _traverserEnumerator ??= GetTraverserEnumerator();
 
         private bool _nextAvailable;
         private bool _fetchedNext;
@@ -109,23 +110,23 @@
         }
 
         /// <inheritdoc />
-        public E Current => GetCurrent<E>();
+        public TEnd? Current => GetCurrent<TEnd>();
 
-        object IEnumerator.Current => GetCurrent();
+        object? IEnumerator.Current => GetCurrent();
 
-        private TReturn GetCurrent<TReturn>()
+        private TReturn? GetCurrent<TReturn>()
         {
             var value = GetCurrent();
             var returnType = typeof(TReturn);
             if (value == null || value.GetType() == returnType)
             {
                 // Avoid evaluating type comparisons
-                return (TReturn) value;
+                return (TReturn?) value;
             }
             return (TReturn) GetValue(returnType, value);
         }
 
-        private object GetCurrent()
+        private object? GetCurrent()
         {
             // Use dynamic to object to prevent runtime dynamic conversion evaluation
             return TraverserEnumerator.Current?.Object;
@@ -134,7 +135,8 @@
         /// <summary>
         /// Gets the value, converting to the expected type when necessary and supported. 
         /// </summary>
-        private static object GetValue(Type type, object value)
+        [return: NotNullIfNotNull("value")]
+        private static object? GetValue(Type type, object? value)
         {
             var genericType = type.GetTypeInfo().IsGenericType
                 ? type.GetTypeInfo().GetGenericTypeDefinition()
@@ -144,7 +146,8 @@
                 var keyType = type.GenericTypeArguments[0];
                 var valueType = type.GenericTypeArguments[1];
                 var mapType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType);
-                var result = (IDictionary) Activator.CreateInstance(mapType);
+                var result = (IDictionary?)Activator.CreateInstance(mapType) ??
+                             throw new InvalidOperationException($"Cannot convert value {value} to a Dictionary.");
                 foreach (DictionaryEntry kv in dictValue)
                 {
                     result.Add(GetValue(keyType, kv.Key), GetValue(valueType, kv.Value));
@@ -155,7 +158,8 @@
             {
                 var childType = type.GenericTypeArguments[0];
                 var listType = typeof(List<>).MakeGenericType(childType);
-                var result = (IList) Activator.CreateInstance(listType);
+                var result = (IList?)Activator.CreateInstance(listType) ??
+                             throw new InvalidOperationException($"Cannot convert value {value} to a list.");
                 foreach (var itemValue in enumerableValue)
                 {
                     result.Add(itemValue);
@@ -169,6 +173,11 @@
         {
             if (Traversers == null)
                 ApplyStrategies();
+            if (Traversers == null)
+            {
+                throw new InvalidOperationException(
+                    $"Cannot enumerate the traversal as there are no {nameof(Traversers)}. Maybe a strategy needs to be added.");
+            }
             return Traversers.GetEnumerator();
         }
 
@@ -196,7 +205,7 @@
         ///     Gets the next result from the traversal.
         /// </summary>
         /// <returns>The result.</returns>
-        public E Next()
+        public TEnd? Next()
         {
             MoveNext();
             return Current;
@@ -207,7 +216,7 @@
         /// </summary>
         /// <param name="amount">The number of results to get.</param>
         /// <returns>The n-results.</returns>
-        public IEnumerable<E> Next(int amount)
+        public IEnumerable<TEnd?> Next(int amount)
         {
             for (var i = 0; i < amount; i++)
                 yield return Next();
@@ -217,7 +226,7 @@
         ///     Iterates all <see cref="Traverser" /> instances in the traversal.
         /// </summary>
         /// <returns>The fully drained traversal.</returns>
-        public ITraversal<S, E> Iterate()
+        public ITraversal<TStart, TEnd> Iterate()
         {
             Bytecode.AddStep("none");
             while (MoveNext())
@@ -240,9 +249,9 @@
         ///     Puts all the results into a <see cref="List{T}" />.
         /// </summary>
         /// <returns>The results in a list.</returns>
-        public IList<E> ToList()
+        public IList<TEnd?> ToList()
         {
-            var objs = new List<E>();
+            var objs = new List<TEnd?>();
             while (MoveNext())
                 objs.Add(Current);
             return objs;
@@ -252,9 +261,9 @@
         ///     Puts all the results into a <see cref="HashSet{T}" />.
         /// </summary>
         /// <returns>The results in a set.</returns>
-        public ISet<E> ToSet()
+        public ISet<TEnd?> ToSet()
         {
-            var objs = new HashSet<E>();
+            var objs = new HashSet<TEnd?>();
             while (MoveNext())
                 objs.Add(Current);
             return objs;
@@ -267,7 +276,7 @@
         /// <param name="callback">The function to execute on the current traversal.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <returns>The result of the executed <paramref name="callback" />.</returns>
-        public async Task<TReturn> Promise<TReturn>(Func<ITraversal<S, E>, TReturn> callback,
+        public async Task<TReturn> Promise<TReturn>(Func<ITraversal<TStart, TEnd>, TReturn> callback,
             CancellationToken cancellationToken = default)
         {
             await ApplyStrategiesAsync(cancellationToken).ConfigureAwait(false);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/EnumWrapper.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/EnumWrapper.cs
index ac0185c..3df6a6d 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/EnumWrapper.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/EnumWrapper.cs
@@ -47,12 +47,12 @@
         /// <param name="enumValue">The value of the enum.</param>
         protected EnumWrapper(string enumName, string enumValue)
         {
-            EnumName = enumName;
-            EnumValue = enumValue;
+            EnumName = enumName ?? throw new ArgumentNullException(nameof(enumName));
+            EnumValue = enumValue ?? throw new ArgumentNullException(nameof(enumValue));
         }
 
         /// <inheritdoc />
-        public bool Equals(EnumWrapper other)
+        public bool Equals(EnumWrapper? other)
         {
             if (ReferenceEquals(null, other)) return false;
             if (ReferenceEquals(this, other)) return true;
@@ -60,7 +60,7 @@
         }
 
         /// <inheritdoc />
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             if (ReferenceEquals(null, obj)) return false;
             if (ReferenceEquals(this, obj)) return true;
@@ -73,8 +73,7 @@
         {
             unchecked
             {
-                return ((EnumName != null ? EnumName.GetHashCode() : 0) * 397) ^
-                       (EnumValue != null ? EnumValue.GetHashCode() : 0);
+                return (EnumName.GetHashCode() * 397) ^ EnumValue.GetHashCode();
             }
         }
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
index c6cf798..2d16336 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
@@ -31,7 +31,7 @@
     /// <summary>
     ///     Graph traversals are the primary way in which graphs are processed.
     /// </summary>
-    public class GraphTraversal<S, E> : DefaultTraversal<S, E>
+    public class GraphTraversal<TStart, TEnd> : DefaultTraversal<TStart, TEnd>
     {
         /// <summary>
         ///     Initializes a new instance of the <see cref="GraphTraversal{SType, EType}" /> class.
@@ -64,115 +64,136 @@
             IsAnonymous = anonymous;
         }
 
-        private static GraphTraversal<S2, E2> Wrap<S2, E2>(GraphTraversal<S, E> traversal)
+        /// <inheritdoc />
+        public override Bytecode Bytecode { get; }
+
+        private static GraphTraversal<TNewStart, TNewEnd> Wrap<TNewStart, TNewEnd>(GraphTraversal<TStart, TEnd> traversal)
         {
-            if (typeof(S2) == typeof(S) && typeof(E2) == typeof(E))
+            if (typeof(TNewStart) == typeof(TStart) && typeof(TNewEnd) == typeof(TEnd))
             {
-                return traversal as GraphTraversal<S2, E2>;
+                return (traversal as GraphTraversal<TNewStart, TNewEnd>)!;
             }
             // New wrapper
-            return new GraphTraversal<S2, E2>(traversal.TraversalStrategies, traversal.Bytecode, traversal.IsAnonymous);
+            return new GraphTraversal<TNewStart, TNewEnd>(traversal.TraversalStrategies, traversal.Bytecode, traversal.IsAnonymous);
         }
 
 
         /// <summary>
         ///     Adds the V step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Vertex> V (params object[] vertexIdsOrElements)
+        public GraphTraversal<TStart, Vertex> V (params object?[]? vertexIdsOrElements)
         {
             if (vertexIdsOrElements == null)
             {
-                Bytecode.AddStep("V", new object[] { null });
+                Bytecode.AddStep("V", new object?[] { null });
             }
             else
             {
-                var args = new List<object>(vertexIdsOrElements.Length);
+                var args = new List<object?>(vertexIdsOrElements.Length);
                 args.AddRange(vertexIdsOrElements);
                 Bytecode.AddStep("V", args.ToArray());
             }
-            return Wrap<S, Vertex>(this);
+            return Wrap<TStart, Vertex>(this);
+        }
+
+        /// <summary>
+        ///     Adds the E step to this <see cref="GraphTraversal{SType, EType}" />.
+        /// </summary>
+        public GraphTraversal<TStart, Edge> E (params object?[]? edgeIdsOrElements)
+        {
+            if (edgeIdsOrElements == null)
+            {
+                Bytecode.AddStep("E", new object?[] { null });
+            }
+            else
+            {
+                var args = new List<object?>(edgeIdsOrElements.Length);
+                args.AddRange(edgeIdsOrElements);
+                Bytecode.AddStep("E", args.ToArray());
+            }
+            return Wrap<TStart, Edge>(this);
         }
 
         /// <summary>
         ///     Adds the addE step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Edge> AddE (string edgeLabel)
+        public GraphTraversal<TStart, Edge> AddE (string edgeLabel)
         {
             Bytecode.AddStep("addE", edgeLabel);
-            return Wrap<S, Edge>(this);
+            return Wrap<TStart, Edge>(this);
         }
 
         /// <summary>
         ///     Adds the addE step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Edge> AddE (ITraversal edgeLabelTraversal)
+        public GraphTraversal<TStart, Edge> AddE (ITraversal edgeLabelTraversal)
         {
             Bytecode.AddStep("addE", edgeLabelTraversal);
-            return Wrap<S, Edge>(this);
+            return Wrap<TStart, Edge>(this);
         }
 
         /// <summary>
         ///     Adds the addV step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Vertex> AddV ()
+        public GraphTraversal<TStart, Vertex> AddV ()
         {
             Bytecode.AddStep("addV");
-            return Wrap<S, Vertex>(this);
+            return Wrap<TStart, Vertex>(this);
         }
 
         /// <summary>
         ///     Adds the addV step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Vertex> AddV (string vertexLabel)
+        public GraphTraversal<TStart, Vertex> AddV (string vertexLabel)
         {
             Bytecode.AddStep("addV", vertexLabel);
-            return Wrap<S, Vertex>(this);
+            return Wrap<TStart, Vertex>(this);
         }
 
         /// <summary>
         ///     Adds the addV step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Vertex> AddV (ITraversal vertexLabelTraversal)
+        public GraphTraversal<TStart, Vertex> AddV (ITraversal vertexLabelTraversal)
         {
             Bytecode.AddStep("addV", vertexLabelTraversal);
-            return Wrap<S, Vertex>(this);
+            return Wrap<TStart, Vertex>(this);
         }
 
         /// <summary>
         ///     Adds the aggregate step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Aggregate (Scope scope, string sideEffectKey)
+        public GraphTraversal<TStart, TEnd> Aggregate (Scope scope, string sideEffectKey)
         {
             Bytecode.AddStep("aggregate", scope, sideEffectKey);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the aggregate step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Aggregate (string sideEffectKey)
+        public GraphTraversal<TStart, TEnd> Aggregate (string sideEffectKey)
         {
             Bytecode.AddStep("aggregate", sideEffectKey);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the and step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> And (params ITraversal[] andTraversals)
+        public GraphTraversal<TStart, TEnd> And (params ITraversal[] andTraversals)
         {
             if (andTraversals == null) throw new ArgumentNullException(nameof(andTraversals));
             
             var args = new List<object>(andTraversals.Length);
             args.AddRange(andTraversals);
             Bytecode.AddStep("and", args.ToArray());
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the as step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> As (string stepLabel, params string[] stepLabels)
+        public GraphTraversal<TStart, TEnd> As (string stepLabel, params string[] stepLabels)
         {
             if (stepLabel == null) throw new ArgumentNullException(nameof(stepLabel));
             if (stepLabels == null) throw new ArgumentNullException(nameof(stepLabels));
@@ -180,219 +201,220 @@
             var args = new List<object>(1 + stepLabels.Length) {stepLabel};
             args.AddRange(stepLabels);
             Bytecode.AddStep("as", args.ToArray());
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the barrier step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Barrier ()
+        public GraphTraversal<TStart, TEnd> Barrier ()
         {
             Bytecode.AddStep("barrier");
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the barrier step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Barrier (IConsumer barrierConsumer)
+        public GraphTraversal<TStart, TEnd> Barrier (IConsumer barrierConsumer)
         {
             Bytecode.AddStep("barrier", barrierConsumer);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the barrier step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Barrier (int maxBarrierSize)
+        public GraphTraversal<TStart, TEnd> Barrier (int maxBarrierSize)
         {
             Bytecode.AddStep("barrier", maxBarrierSize);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the both step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Vertex> Both (params string[] edgeLabels)
+        public GraphTraversal<TStart, Vertex> Both (params string?[] edgeLabels)
         {
             if (edgeLabels == null) throw new ArgumentNullException(nameof(edgeLabels));
             
-            var args = new List<object>(edgeLabels.Length);
+            var args = new List<object?>(edgeLabels.Length);
             args.AddRange(edgeLabels);
             Bytecode.AddStep("both", args.ToArray());
-            return Wrap<S, Vertex>(this);
+            return Wrap<TStart, Vertex>(this);
         }
 
         /// <summary>
         ///     Adds the bothE step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Edge> BothE (params string[] edgeLabels)
+        public GraphTraversal<TStart, Edge> BothE (params string?[] edgeLabels)
         {
             if (edgeLabels == null) throw new ArgumentNullException(nameof(edgeLabels));
             
-            var args = new List<object>(edgeLabels.Length);
+            var args = new List<object?>(edgeLabels.Length);
             args.AddRange(edgeLabels);
             Bytecode.AddStep("bothE", args.ToArray());
-            return Wrap<S, Edge>(this);
+            return Wrap<TStart, Edge>(this);
         }
 
         /// <summary>
         ///     Adds the bothV step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Vertex> BothV ()
+        public GraphTraversal<TStart, Vertex> BothV ()
         {
             Bytecode.AddStep("bothV");
-            return Wrap<S, Vertex>(this);
+            return Wrap<TStart, Vertex>(this);
         }
 
         /// <summary>
         ///     Adds the branch step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Branch<E2> (IFunction function)
+        public GraphTraversal<TStart, TNewEnd> Branch<TNewEnd> (IFunction? function)
         {
             Bytecode.AddStep("branch", function);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the branch step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Branch<E2> (ITraversal branchTraversal)
+        public GraphTraversal<TStart, TNewEnd> Branch<TNewEnd> (ITraversal branchTraversal)
         {
             Bytecode.AddStep("branch", branchTraversal);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the by step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> By ()
+        public GraphTraversal<TStart, TEnd> By ()
         {
             Bytecode.AddStep("by");
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the by step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> By (IComparator comparator)
+        public GraphTraversal<TStart, TEnd> By (IComparator comparator)
         {
             Bytecode.AddStep("by", comparator);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the by step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> By (IFunction function)
+        public GraphTraversal<TStart, TEnd> By (IFunction function)
         {
             Bytecode.AddStep("by", function);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the by step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> By (IFunction function, IComparator comparator)
+        public GraphTraversal<TStart, TEnd> By (IFunction function, IComparator comparator)
         {
             Bytecode.AddStep("by", function, comparator);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the by step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> By (Order order)
+        public GraphTraversal<TStart, TEnd> By (Order order)
         {
             Bytecode.AddStep("by", order);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the by step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> By (string key)
+        public GraphTraversal<TStart, TEnd> By (string? key)
         {
             Bytecode.AddStep("by", key);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the by step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> By (string key, IComparator comparator)
+        public GraphTraversal<TStart, TEnd> By (string? key, IComparator comparator)
         {
             Bytecode.AddStep("by", key, comparator);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the by step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> By (T token)
+        public GraphTraversal<TStart, TEnd> By (T token)
         {
             Bytecode.AddStep("by", token);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the by step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> By (ITraversal traversal)
+        public GraphTraversal<TStart, TEnd> By (ITraversal traversal)
         {
             Bytecode.AddStep("by", traversal);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the by step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> By (ITraversal traversal, IComparator comparator)
+        public GraphTraversal<TStart, TEnd> By (ITraversal traversal, IComparator comparator)
         {
             Bytecode.AddStep("by", traversal, comparator);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the call step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Call<E2> (string service)
+        public GraphTraversal<TStart, TNewEnd> Call<TNewEnd> (string? service)
         {
             Bytecode.AddStep("call", service);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the call step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Call<E2> (string service, ITraversal t)
+        public GraphTraversal<TStart, TNewEnd> Call<TNewEnd> (string? service, ITraversal? t)
         {
             Bytecode.AddStep("call", service, t);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the call step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Call<E2> (string service, IDictionary<object,object> m)
+        public GraphTraversal<TStart, TNewEnd> Call<TNewEnd> (string? service, IDictionary<object,object>? m)
         {
             Bytecode.AddStep("call", service, m);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the call step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Call<E2> (string service, IDictionary<object,object> m, ITraversal t)
+        public GraphTraversal<TStart, TNewEnd> Call<TNewEnd>(string? service, IDictionary<object, object>? m,
+            ITraversal? t)
         {
             Bytecode.AddStep("call", service, m, t);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the cap step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Cap<E2> (string sideEffectKey, params string[] sideEffectKeys)
+        public GraphTraversal<TStart, TNewEnd> Cap<TNewEnd> (string sideEffectKey, params string[] sideEffectKeys)
         {
             if (sideEffectKey == null) throw new ArgumentNullException(nameof(sideEffectKey));
             if (sideEffectKeys == null) throw new ArgumentNullException(nameof(sideEffectKeys));
@@ -400,1662 +422,1663 @@
             var args = new List<object>(1 + sideEffectKeys.Length) { sideEffectKey };
             args.AddRange(sideEffectKeys);
             Bytecode.AddStep("cap", args.ToArray());
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the choose step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Choose<E2> (IFunction choiceFunction)
+        public GraphTraversal<TStart, TNewEnd> Choose<TNewEnd> (IFunction choiceFunction)
         {
             Bytecode.AddStep("choose", choiceFunction);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the choose step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Choose<E2> (IPredicate choosePredicate, ITraversal trueChoice)
+        public GraphTraversal<TStart, TNewEnd> Choose<TNewEnd> (IPredicate choosePredicate, ITraversal trueChoice)
         {
             Bytecode.AddStep("choose", choosePredicate, trueChoice);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the choose step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Choose<E2> (IPredicate choosePredicate, ITraversal trueChoice, ITraversal falseChoice)
+        public GraphTraversal<TStart, TNewEnd> Choose<TNewEnd> (IPredicate choosePredicate, ITraversal trueChoice, ITraversal falseChoice)
         {
             Bytecode.AddStep("choose", choosePredicate, trueChoice, falseChoice);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the choose step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Choose<E2> (ITraversal choiceTraversal)
+        public GraphTraversal<TStart, TNewEnd> Choose<TNewEnd> (ITraversal choiceTraversal)
         {
             Bytecode.AddStep("choose", choiceTraversal);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the choose step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Choose<E2> (ITraversal traversalPredicate, ITraversal trueChoice)
+        public GraphTraversal<TStart, TNewEnd> Choose<TNewEnd> (ITraversal traversalPredicate, ITraversal trueChoice)
         {
             Bytecode.AddStep("choose", traversalPredicate, trueChoice);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the choose step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Choose<E2> (ITraversal traversalPredicate, ITraversal trueChoice, ITraversal falseChoice)
+        public GraphTraversal<TStart, TNewEnd> Choose<TNewEnd> (ITraversal traversalPredicate, ITraversal trueChoice, ITraversal falseChoice)
         {
             Bytecode.AddStep("choose", traversalPredicate, trueChoice, falseChoice);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the coalesce step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Coalesce<E2> (params ITraversal[] coalesceTraversals)
+        public GraphTraversal<TStart, TNewEnd> Coalesce<TNewEnd> (params ITraversal[] coalesceTraversals)
         {
             if (coalesceTraversals == null) throw new ArgumentNullException(nameof(coalesceTraversals));
 
             var args = new List<object>(coalesceTraversals.Length);
             args.AddRange(coalesceTraversals);
             Bytecode.AddStep("coalesce", args.ToArray());
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the coin step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Coin (double probability)
+        public GraphTraversal<TStart, TEnd> Coin (double probability)
         {
             Bytecode.AddStep("coin", probability);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the connectedComponent step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> ConnectedComponent ()
+        public GraphTraversal<TStart, TEnd> ConnectedComponent ()
         {
             Bytecode.AddStep("connectedComponent");
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the constant step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Constant<E2> (E2 e)
+        public GraphTraversal<TStart, TNewEnd> Constant<TNewEnd> (TNewEnd e)
         {
             Bytecode.AddStep("constant", e);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the count step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, long> Count ()
+        public GraphTraversal<TStart, long> Count ()
         {
             Bytecode.AddStep("count");
-            return Wrap<S, long>(this);
+            return Wrap<TStart, long>(this);
         }
 
         /// <summary>
         ///     Adds the count step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, long> Count (Scope scope)
+        public GraphTraversal<TStart, long> Count (Scope scope)
         {
             Bytecode.AddStep("count", scope);
-            return Wrap<S, long>(this);
+            return Wrap<TStart, long>(this);
         }
 
         /// <summary>
         ///     Adds the cyclicPath step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> CyclicPath ()
+        public GraphTraversal<TStart, TEnd> CyclicPath ()
         {
             Bytecode.AddStep("cyclicPath");
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the dedup step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Dedup (Scope scope, params string[] dedupLabels)
+        public GraphTraversal<TStart, TEnd> Dedup (Scope scope, params string?[] dedupLabels)
         {
             if (dedupLabels == null) throw new ArgumentNullException(nameof(dedupLabels));
 
-            var args = new List<object>(1 + dedupLabels.Length) { scope };
+            var args = new List<object?>(1 + dedupLabels.Length) { scope };
             args.AddRange(dedupLabels);
             Bytecode.AddStep("dedup", args.ToArray());
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the dedup step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Dedup (params string[] dedupLabels)
+        public GraphTraversal<TStart, TEnd> Dedup (params string?[] dedupLabels)
         {
             if (dedupLabels == null) throw new ArgumentNullException(nameof(dedupLabels));
 
-            var args = new List<object>(dedupLabels.Length);
+            var args = new List<object?>(dedupLabels.Length);
             args.AddRange(dedupLabels);
             Bytecode.AddStep("dedup", args.ToArray());
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the drop step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Drop ()
+        public GraphTraversal<TStart, TEnd> Drop ()
         {
             Bytecode.AddStep("drop");
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the element step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Element> Element ()
+        public GraphTraversal<TStart, Element> Element ()
         {
             Bytecode.AddStep("element");
-            return Wrap<S, Element>(this);
+            return Wrap<TStart, Element>(this);
         }
 
         /// <summary>
         ///     Adds the elementMap step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, IDictionary<object, E2>> ElementMap<E2> (params string[] propertyKeys)
+        public GraphTraversal<TStart, IDictionary<object, TNewEnd>> ElementMap<TNewEnd> (params string?[] propertyKeys)
         {
             if (propertyKeys == null) throw new ArgumentNullException(nameof(propertyKeys));
             
-            var args = new List<object>(0 + propertyKeys.Length);
+            var args = new List<object?>(0 + propertyKeys.Length);
             args.AddRange(propertyKeys);
             Bytecode.AddStep("elementMap", args.ToArray());
-            return Wrap<S, IDictionary<object, E2>>(this);
+            return Wrap<TStart, IDictionary<object, TNewEnd>>(this);
         }
 
         /// <summary>
         ///     Adds the emit step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Emit ()
+        public GraphTraversal<TStart, TEnd> Emit ()
         {
             Bytecode.AddStep("emit");
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the emit step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Emit (IPredicate emitPredicate)
+        public GraphTraversal<TStart, TEnd> Emit (IPredicate emitPredicate)
         {
             Bytecode.AddStep("emit", emitPredicate);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the emit step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Emit (ITraversal emitTraversal)
+        public GraphTraversal<TStart, TEnd> Emit (ITraversal emitTraversal)
         {
             Bytecode.AddStep("emit", emitTraversal);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the fail step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Fail ()
+        public GraphTraversal<TStart, TEnd> Fail ()
         {
             Bytecode.AddStep("fail");
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the fail step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Fail (string msg)
+        public GraphTraversal<TStart, TEnd> Fail (string? msg)
         {
             Bytecode.AddStep("fail", msg);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the fail step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Fail (string msg, IDictionary<string,object> m)
+        public GraphTraversal<TStart, TEnd> Fail (string? msg, IDictionary<string,object> m)
         {
             Bytecode.AddStep("fail", msg, m);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the filter step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Filter (IPredicate predicate)
+        public GraphTraversal<TStart, TEnd> Filter (IPredicate? predicate)
         {
             Bytecode.AddStep("filter", predicate);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the filter step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Filter (ITraversal filterTraversal)
+        public GraphTraversal<TStart, TEnd> Filter (ITraversal filterTraversal)
         {
             Bytecode.AddStep("filter", filterTraversal);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the flatMap step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> FlatMap<E2> (IFunction function)
+        public GraphTraversal<TStart, TNewEnd> FlatMap<TNewEnd> (IFunction? function)
         {
             Bytecode.AddStep("flatMap", function);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the flatMap step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> FlatMap<E2> (ITraversal flatMapTraversal)
+        public GraphTraversal<TStart, TNewEnd> FlatMap<TNewEnd> (ITraversal flatMapTraversal)
         {
             Bytecode.AddStep("flatMap", flatMapTraversal);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the fold step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, IList<E>> Fold ()
+        public GraphTraversal<TStart, IList<TEnd>> Fold ()
         {
             Bytecode.AddStep("fold");
-            return Wrap<S, IList<E>>(this);
+            return Wrap<TStart, IList<TEnd>>(this);
         }
 
         /// <summary>
         ///     Adds the fold step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Fold<E2> (E2 seed, IBiFunction foldFunction)
+        public GraphTraversal<TStart, TNewEnd> Fold<TNewEnd> (TNewEnd seed, IBiFunction? foldFunction)
         {
             Bytecode.AddStep("fold", seed, foldFunction);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the from step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> From (string fromStepLabel)
+        public GraphTraversal<TStart, TEnd> From (string? fromStepLabel)
         {
             Bytecode.AddStep("from", fromStepLabel);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the from step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> From (ITraversal fromVertex)
+        public GraphTraversal<TStart, TEnd> From (ITraversal fromVertex)
         {
             Bytecode.AddStep("from", fromVertex);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the from step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> From (Vertex fromVertex)
+        public GraphTraversal<TStart, TEnd> From (Vertex? fromVertex)
         {
             Bytecode.AddStep("from", fromVertex);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the group step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, IDictionary<K, V>> Group<K, V> ()
+        public GraphTraversal<TStart, IDictionary<K, V>> Group<K, V> ()
         {
             Bytecode.AddStep("group");
-            return Wrap<S, IDictionary<K, V>>(this);
+            return Wrap<TStart, IDictionary<K, V>>(this);
         }
 
         /// <summary>
         ///     Adds the group step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Group (string sideEffectKey)
+        public GraphTraversal<TStart, TEnd> Group (string sideEffectKey)
         {
             Bytecode.AddStep("group", sideEffectKey);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the groupCount step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, IDictionary<K, long>> GroupCount<K> ()
+        public GraphTraversal<TStart, IDictionary<K, long>> GroupCount<K> ()
         {
             Bytecode.AddStep("groupCount");
-            return Wrap<S, IDictionary<K, long>>(this);
+            return Wrap<TStart, IDictionary<K, long>>(this);
         }
 
         /// <summary>
         ///     Adds the groupCount step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> GroupCount (string sideEffectKey)
+        public GraphTraversal<TStart, TEnd> GroupCount (string sideEffectKey)
         {
             Bytecode.AddStep("groupCount", sideEffectKey);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the has step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Has (string propertyKey)
+        public GraphTraversal<TStart, TEnd> Has (string? propertyKey)
         {
             Bytecode.AddStep("has", propertyKey);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the has step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Has (string propertyKey, object value)
+        public GraphTraversal<TStart, TEnd> Has (string? propertyKey, object? value)
         {
             Bytecode.AddStep("has", propertyKey, value);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the has step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Has (string propertyKey, P predicate)
+        public GraphTraversal<TStart, TEnd> Has (string? propertyKey, P? predicate)
         {
             Bytecode.AddStep("has", propertyKey, predicate);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the has step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Has (string label, string propertyKey, object value)
+        public GraphTraversal<TStart, TEnd> Has (string? label, string? propertyKey, object? value)
         {
             Bytecode.AddStep("has", label, propertyKey, value);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the has step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Has (string label, string propertyKey, P predicate)
+        public GraphTraversal<TStart, TEnd> Has (string? label, string? propertyKey, P? predicate)
         {
             Bytecode.AddStep("has", label, propertyKey, predicate);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the has step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Has (string propertyKey, ITraversal propertyTraversal)
+        public GraphTraversal<TStart, TEnd> Has (string? propertyKey, ITraversal propertyTraversal)
         {
             Bytecode.AddStep("has", propertyKey, propertyTraversal);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the has step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Has (T accessor, object value)
+        public GraphTraversal<TStart, TEnd> Has (T accessor, object? value)
         {
             Bytecode.AddStep("has", accessor, value);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the has step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Has (T accessor, P predicate)
+        public GraphTraversal<TStart, TEnd> Has (T accessor, P? predicate)
         {
             Bytecode.AddStep("has", accessor, predicate);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the has step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Has (T accessor, ITraversal propertyTraversal)
+        public GraphTraversal<TStart, TEnd> Has (T accessor, ITraversal propertyTraversal)
         {
             Bytecode.AddStep("has", accessor, propertyTraversal);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the hasId step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> HasId (object id, params object[] otherIds)
+        public GraphTraversal<TStart, TEnd> HasId (object? id, params object?[]? otherIds)
         {
-            List<object> args;
+            List<object?> args;
             if (otherIds == null)
             {
-                args = new List<object> { id, null };
+                args = new List<object?> { id, null };
             }
             else
             {
-                args = new List<object>(1 + otherIds.Length) { id };
+                args = new List<object?>(1 + otherIds.Length) { id };
                 args.AddRange(otherIds);
             }
             Bytecode.AddStep("hasId", args.ToArray());
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the hasId step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> HasId (P predicate)
+        public GraphTraversal<TStart, TEnd> HasId (P? predicate)
         {
             Bytecode.AddStep("hasId", predicate);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the hasKey step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> HasKey (P predicate)
+        public GraphTraversal<TStart, TEnd> HasKey (P? predicate)
         {
             Bytecode.AddStep("hasKey", predicate);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the hasKey step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> HasKey (string label, params string[] otherLabels)
+        public GraphTraversal<TStart, TEnd> HasKey (string? label, params string?[]? otherLabels)
         {
-            List<object> args;
+            List<object?> args;
             if (otherLabels == null)
             {
-                args = new List<object> { label, null };
+                args = new List<object?> { label, null };
             }
             else
             {
-                args = new List<object>(1 + otherLabels.Length) { label };
+                args = new List<object?>(1 + otherLabels.Length) { label };
                 args.AddRange(otherLabels);
             }
             Bytecode.AddStep("hasKey", args.ToArray());
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the hasLabel step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> HasLabel (P predicate)
+        public GraphTraversal<TStart, TEnd> HasLabel (P? predicate)
         {
             Bytecode.AddStep("hasLabel", predicate);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the hasLabel step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> HasLabel (string label, params string[] otherLabels)
+        public GraphTraversal<TStart, TEnd> HasLabel (string? label, params string?[]? otherLabels)
         {
-            List<object> args;
+            List<object?> args;
             if (otherLabels == null)
             {
-                args = new List<object> { label, null };
+                args = new List<object?> { label, null };
             }
             else
             {
-                args = new List<object>(1 + otherLabels.Length) { label };
+                args = new List<object?>(1 + otherLabels.Length) { label };
                 args.AddRange(otherLabels);
             }
             Bytecode.AddStep("hasLabel", args.ToArray());
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the hasNot step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> HasNot (string propertyKey)
+        public GraphTraversal<TStart, TEnd> HasNot (string? propertyKey)
         {
             Bytecode.AddStep("hasNot", propertyKey);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the hasValue step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> HasValue (object value, params object[] otherValues)
+        public GraphTraversal<TStart, TEnd> HasValue (object? value, params object?[]? otherValues)
         {
-            List<object> args;
+            List<object?> args;
             if (otherValues == null)
             {
-                args = new List<object> { value, null };
+                args = new List<object?> { value, null };
             }
             else
             {
-                args = new List<object>(1 + otherValues.Length) { value };
+                args = new List<object?>(1 + otherValues.Length) { value };
                 args.AddRange(otherValues);
             }
             Bytecode.AddStep("hasValue", args.ToArray());
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the hasValue step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> HasValue (P predicate)
+        public GraphTraversal<TStart, TEnd> HasValue (P? predicate)
         {
             Bytecode.AddStep("hasValue", predicate);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the id step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, object> Id ()
+        public GraphTraversal<TStart, object> Id ()
         {
             Bytecode.AddStep("id");
-            return Wrap<S, object>(this);
+            return Wrap<TStart, object>(this);
         }
 
         /// <summary>
         ///     Adds the identity step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Identity ()
+        public GraphTraversal<TStart, TEnd> Identity ()
         {
             Bytecode.AddStep("identity");
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the in step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Vertex> In (params string[] edgeLabels)
+        public GraphTraversal<TStart, Vertex> In (params string?[] edgeLabels)
         {
             if (edgeLabels == null) throw new ArgumentNullException(nameof(edgeLabels));
             
-            var args = new List<object>(edgeLabels.Length);
+            var args = new List<object?>(edgeLabels.Length);
             args.AddRange(edgeLabels);
             Bytecode.AddStep("in", args.ToArray());
-            return Wrap<S, Vertex>(this);
+            return Wrap<TStart, Vertex>(this);
         }
 
         /// <summary>
         ///     Adds the inE step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Edge> InE (params string[] edgeLabels)
+        public GraphTraversal<TStart, Edge> InE (params string?[] edgeLabels)
         {
             if (edgeLabels == null) throw new ArgumentNullException(nameof(edgeLabels));
             
-            var args = new List<object>(edgeLabels.Length);
+            var args = new List<object?>(edgeLabels.Length);
             args.AddRange(edgeLabels);
             Bytecode.AddStep("inE", args.ToArray());
-            return Wrap<S, Edge>(this);
+            return Wrap<TStart, Edge>(this);
         }
 
         /// <summary>
         ///     Adds the inV step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Vertex> InV ()
+        public GraphTraversal<TStart, Vertex> InV ()
         {
             Bytecode.AddStep("inV");
-            return Wrap<S, Vertex>(this);
+            return Wrap<TStart, Vertex>(this);
         }
 
         /// <summary>
         ///     Adds the index step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Index<E2> ()
+        public GraphTraversal<TStart, TNewEnd> Index<TNewEnd> ()
         {
             Bytecode.AddStep("index");
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the inject step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Inject (params E[] injections)
+        public GraphTraversal<TStart, TEnd> Inject (params TEnd?[]? injections)
         {
             // null injections is treated as g.inject(null) meaning inject a single null traverser
             if (injections == null)
             {
-                Bytecode.AddStep("inject", new object[] { null });
+                Bytecode.AddStep("inject", new object?[] { null });
             }
             else
             {
-                var args = new List<object>(injections.Length);
-                args.AddRange(injections.Cast<object>());
+                var args = new List<object?>(injections.Length);
+                args.AddRange(injections.Cast<object?>());
                 Bytecode.AddStep("inject", args.ToArray());
             }
 
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the is step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Is (object value)
+        public GraphTraversal<TStart, TEnd> Is (object? value)
         {
             Bytecode.AddStep("is", value);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the is step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Is (P predicate)
+        public GraphTraversal<TStart, TEnd> Is (P? predicate)
         {
             Bytecode.AddStep("is", predicate);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the key step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, string> Key ()
+        public GraphTraversal<TStart, string> Key ()
         {
             Bytecode.AddStep("key");
-            return Wrap<S, string>(this);
+            return Wrap<TStart, string>(this);
         }
 
         /// <summary>
         ///     Adds the label step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, string> Label ()
+        public GraphTraversal<TStart, string> Label ()
         {
             Bytecode.AddStep("label");
-            return Wrap<S, string>(this);
+            return Wrap<TStart, string>(this);
         }
 
         /// <summary>
         ///     Adds the limit step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Limit<E2> (Scope scope, long limit)
+        public GraphTraversal<TStart, TNewEnd> Limit<TNewEnd> (Scope scope, long limit)
         {
             Bytecode.AddStep("limit", scope, limit);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the limit step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Limit<E2> (long limit)
+        public GraphTraversal<TStart, TNewEnd> Limit<TNewEnd> (long limit)
         {
             Bytecode.AddStep("limit", limit);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the local step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Local<E2> (ITraversal localTraversal)
+        public GraphTraversal<TStart, TNewEnd> Local<TNewEnd> (ITraversal localTraversal)
         {
             Bytecode.AddStep("local", localTraversal);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the loops step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, int> Loops ()
+        public GraphTraversal<TStart, int> Loops ()
         {
             Bytecode.AddStep("loops");
-            return Wrap<S, int>(this);
+            return Wrap<TStart, int>(this);
         }
 
         /// <summary>
         ///     Adds the loops step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, int> Loops (string loopName)
+        public GraphTraversal<TStart, int> Loops (string? loopName)
         {
             Bytecode.AddStep("loops", loopName);
-            return Wrap<S, int>(this);
+            return Wrap<TStart, int>(this);
         }
 
         /// <summary>
         ///     Adds the map step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Map<E2> (IFunction function)
+        public GraphTraversal<TStart, TNewEnd> Map<TNewEnd> (IFunction? function)
         {
             Bytecode.AddStep("map", function);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the map step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Map<E2> (ITraversal mapTraversal)
+        public GraphTraversal<TStart, TNewEnd> Map<TNewEnd> (ITraversal mapTraversal)
         {
             Bytecode.AddStep("map", mapTraversal);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the match step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, IDictionary<string, E2>> Match<E2> (params ITraversal[] matchTraversals)
+        public GraphTraversal<TStart, IDictionary<string, TNewEnd>> Match<TNewEnd> (params ITraversal[] matchTraversals)
         {
             if (matchTraversals == null) throw new ArgumentNullException(nameof(matchTraversals));
 
             var args = new List<object>(matchTraversals.Length);
             args.AddRange(matchTraversals);
             Bytecode.AddStep("match", args.ToArray());
-            return Wrap<S, IDictionary<string, E2>>(this);
+            return Wrap<TStart, IDictionary<string, TNewEnd>>(this);
         }
 
         /// <summary>
         ///     Adds the math step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, double> Math (string expression)
+        public GraphTraversal<TStart, double> Math (string expression)
         {
             Bytecode.AddStep("math", expression);
-            return Wrap<S, double>(this);
+            return Wrap<TStart, double>(this);
         }
 
         /// <summary>
         ///     Adds the max step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Max<E2> ()
+        public GraphTraversal<TStart, TNewEnd> Max<TNewEnd> ()
         {
             Bytecode.AddStep("max");
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the max step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Max<E2> (Scope scope)
+        public GraphTraversal<TStart, TNewEnd> Max<TNewEnd> (Scope scope)
         {
             Bytecode.AddStep("max", scope);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the mean step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Mean<E2> ()
+        public GraphTraversal<TStart, TNewEnd> Mean<TNewEnd> ()
         {
             Bytecode.AddStep("mean");
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the mean step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Mean<E2> (Scope scope)
+        public GraphTraversal<TStart, TNewEnd> Mean<TNewEnd> (Scope scope)
         {
             Bytecode.AddStep("mean", scope);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the mergeE step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Edge> MergeE ()
+        public GraphTraversal<TStart, Edge> MergeE ()
         {
             Bytecode.AddStep("mergeE");
-            return Wrap<S, Edge>(this);
+            return Wrap<TStart, Edge>(this);
         }
 
         /// <summary>
         ///     Adds the mergeE step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Edge> MergeE (IDictionary<object,object> m)
+        public GraphTraversal<TStart, Edge> MergeE (IDictionary<object,object>? m)
         {
             Bytecode.AddStep("mergeE", m);
-            return Wrap<S, Edge>(this);
+            return Wrap<TStart, Edge>(this);
         }
 
         /// <summary>
         ///     Adds the mergeE step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Edge> MergeE (ITraversal t)
+        public GraphTraversal<TStart, Edge> MergeE (ITraversal? t)
         {
             Bytecode.AddStep("mergeE", t);
-            return Wrap<S, Edge>(this);
+            return Wrap<TStart, Edge>(this);
         }
 
         /// <summary>
         ///     Adds the mergeV step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Vertex> MergeV ()
+        public GraphTraversal<TStart, Vertex> MergeV ()
         {
             Bytecode.AddStep("mergeV");
-            return Wrap<S, Vertex>(this);
+            return Wrap<TStart, Vertex>(this);
         }
 
         /// <summary>
         ///     Adds the mergeV step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Vertex> MergeV (IDictionary<object,object> m)
+        public GraphTraversal<TStart, Vertex> MergeV (IDictionary<object,object>? m)
         {
             Bytecode.AddStep("mergeV", m);
-            return Wrap<S, Vertex>(this);
+            return Wrap<TStart, Vertex>(this);
         }
 
         /// <summary>
         ///     Adds the mergeV step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Vertex> MergeV (ITraversal t)
+        public GraphTraversal<TStart, Vertex> MergeV (ITraversal? t)
         {
             Bytecode.AddStep("mergeV", t);
-            return Wrap<S, Vertex>(this);
+            return Wrap<TStart, Vertex>(this);
         }
 
         /// <summary>
         ///     Adds the min step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Min<E2> ()
+        public GraphTraversal<TStart, TNewEnd> Min<TNewEnd> ()
         {
             Bytecode.AddStep("min");
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the min step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Min<E2> (Scope scope)
+        public GraphTraversal<TStart, TNewEnd> Min<TNewEnd> (Scope scope)
         {
             Bytecode.AddStep("min", scope);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the none step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> None ()
+        public GraphTraversal<TStart, TEnd> None ()
         {
             Bytecode.AddStep("none");
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the not step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Not (ITraversal notTraversal)
+        public GraphTraversal<TStart, TEnd> Not (ITraversal notTraversal)
         {
             Bytecode.AddStep("not", notTraversal);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the option step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Option (object pickToken, ITraversal traversalOption)
+        public GraphTraversal<TStart, TEnd> Option (object pickToken, ITraversal? traversalOption)
         {
             Bytecode.AddStep("option", pickToken, traversalOption);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the option step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Option (object pickToken, IDictionary<object,object> traversalOption)
+        public GraphTraversal<TStart, TEnd> Option (object pickToken, IDictionary<object,object>? traversalOption)
         {
             Bytecode.AddStep("option", pickToken, traversalOption);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the option step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Option (ITraversal traversalOption)
+        public GraphTraversal<TStart, TEnd> Option (ITraversal? traversalOption)
         {
             Bytecode.AddStep("option", traversalOption);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the optional step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Optional<E2> (ITraversal optionalTraversal)
+        public GraphTraversal<TStart, TNewEnd> Optional<TNewEnd> (ITraversal optionalTraversal)
         {
             Bytecode.AddStep("optional", optionalTraversal);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the or step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Or (params ITraversal[] orTraversals)
+        public GraphTraversal<TStart, TEnd> Or (params ITraversal[] orTraversals)
         {
             if (orTraversals == null) throw new ArgumentNullException(nameof(orTraversals));
 
             var args = new List<object>(orTraversals.Length);
             args.AddRange(orTraversals);
             Bytecode.AddStep("or", args.ToArray());
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the order step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Order ()
+        public GraphTraversal<TStart, TEnd> Order ()
         {
             Bytecode.AddStep("order");
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the order step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Order (Scope scope)
+        public GraphTraversal<TStart, TEnd> Order (Scope scope)
         {
             Bytecode.AddStep("order", scope);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the otherV step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Vertex> OtherV ()
+        public GraphTraversal<TStart, Vertex> OtherV ()
         {
             Bytecode.AddStep("otherV");
-            return Wrap<S, Vertex>(this);
+            return Wrap<TStart, Vertex>(this);
         }
 
         /// <summary>
         ///     Adds the out step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Vertex> Out (params string[] edgeLabels)
+        public GraphTraversal<TStart, Vertex> Out (params string?[] edgeLabels)
         {
             if (edgeLabels == null) throw new ArgumentNullException(nameof(edgeLabels));
             
-            var args = new List<object>(edgeLabels.Length);
+            var args = new List<object?>(edgeLabels.Length);
             args.AddRange(edgeLabels);
             Bytecode.AddStep("out", args.ToArray());
-            return Wrap<S, Vertex>(this);
+            return Wrap<TStart, Vertex>(this);
         }
 
         /// <summary>
         ///     Adds the outE step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Edge> OutE (params string[] edgeLabels)
+        public GraphTraversal<TStart, Edge> OutE (params string?[] edgeLabels)
         {
             if (edgeLabels == null) throw new ArgumentNullException(nameof(edgeLabels));
             
-            var args = new List<object>(edgeLabels.Length);
+            var args = new List<object?>(edgeLabels.Length);
             args.AddRange(edgeLabels);
             Bytecode.AddStep("outE", args.ToArray());
-            return Wrap<S, Edge>(this);
+            return Wrap<TStart, Edge>(this);
         }
 
         /// <summary>
         ///     Adds the outV step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Vertex> OutV ()
+        public GraphTraversal<TStart, Vertex> OutV ()
         {
             Bytecode.AddStep("outV");
-            return Wrap<S, Vertex>(this);
+            return Wrap<TStart, Vertex>(this);
         }
 
         /// <summary>
         ///     Adds the pageRank step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> PageRank ()
+        public GraphTraversal<TStart, TEnd> PageRank ()
         {
             Bytecode.AddStep("pageRank");
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the pageRank step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> PageRank (double alpha)
+        public GraphTraversal<TStart, TEnd> PageRank (double alpha)
         {
             Bytecode.AddStep("pageRank", alpha);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the path step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Path> Path ()
+        public GraphTraversal<TStart, Path> Path ()
         {
             Bytecode.AddStep("path");
-            return Wrap<S, Path>(this);
+            return Wrap<TStart, Path>(this);
         }
 
         /// <summary>
         ///     Adds the peerPressure step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> PeerPressure ()
+        public GraphTraversal<TStart, TEnd> PeerPressure ()
         {
             Bytecode.AddStep("peerPressure");
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the profile step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Profile<E2> ()
+        public GraphTraversal<TStart, TNewEnd> Profile<TNewEnd> ()
         {
             Bytecode.AddStep("profile");
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the profile step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Profile (string sideEffectKey)
+        public GraphTraversal<TStart, TEnd> Profile (string sideEffectKey)
         {
             Bytecode.AddStep("profile", sideEffectKey);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the program step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Program (object vertexProgram)
+        public GraphTraversal<TStart, TEnd> Program (object vertexProgram)
         {
             Bytecode.AddStep("program", vertexProgram);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the project step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, IDictionary<string, E2>> Project<E2> (string projectKey, params string[] otherProjectKeys)
+        public GraphTraversal<TStart, IDictionary<string, TNewEnd>> Project<TNewEnd>(string? projectKey,
+            params string?[] otherProjectKeys)
         {
             // Using null as a key is allowed in Java, but we cannot support it in .NET as null is not allowed as a
             //  Dictionary key.
             if (projectKey == null) throw new ArgumentNullException(nameof(projectKey));
             if (otherProjectKeys == null) throw new ArgumentNullException(nameof(otherProjectKeys));
             
-            var args = new List<object>(1 + otherProjectKeys.Length) { projectKey };
+            var args = new List<object?>(1 + otherProjectKeys.Length) { projectKey };
             args.AddRange(otherProjectKeys);
             Bytecode.AddStep("project", args.ToArray());
-            return Wrap<S, IDictionary<string, E2>>(this);
+            return Wrap<TStart, IDictionary<string, TNewEnd>>(this);
         }
 
         /// <summary>
         ///     Adds the properties step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Properties<E2> (params string[] propertyKeys)
+        public GraphTraversal<TStart, TNewEnd> Properties<TNewEnd> (params string?[] propertyKeys)
         {
             // Using null as a key is allowed in Java, but we cannot support it in .NET as null is not allowed as a
             //  Dictionary key.
             if (propertyKeys == null) throw new ArgumentNullException(nameof(propertyKeys));
             
-            var args = new List<object>(propertyKeys.Length);
+            var args = new List<object?>(propertyKeys.Length);
             args.AddRange(propertyKeys);
             Bytecode.AddStep("properties", args.ToArray());
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the property step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Property(Cardinality cardinality, object key, object value,
-            params object[] keyValues)
+        public GraphTraversal<TStart, TEnd> Property(Cardinality cardinality, object? key, object? value,
+            params object?[] keyValues)
         {
             if (keyValues == null) throw new ArgumentNullException(nameof(keyValues));
 
-            var args = new List<object>(3 + keyValues.Length) { cardinality, key, value };
+            var args = new List<object?>(3 + keyValues.Length) { cardinality, key, value };
             args.AddRange(keyValues);
             Bytecode.AddStep("property", args.ToArray());
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the property step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Property (object key, object value, params object[] keyValues)
+        public GraphTraversal<TStart, TEnd> Property (object? key, object? value, params object?[] keyValues)
         {
             if (keyValues == null) throw new ArgumentNullException(nameof(keyValues));
 
-            var args = new List<object>(2 + keyValues.Length) { key, value };
+            var args = new List<object?>(2 + keyValues.Length) { key, value };
             args.AddRange(keyValues);
             Bytecode.AddStep("property", args.ToArray());
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the propertyMap step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, IDictionary<string, E2>> PropertyMap<E2> (params string[] propertyKeys)
+        public GraphTraversal<TStart, IDictionary<string, TNewEnd>> PropertyMap<TNewEnd> (params string?[] propertyKeys)
         {
             if (propertyKeys == null) throw new ArgumentNullException(nameof(propertyKeys));
             
-            var args = new List<object>(propertyKeys.Length);
+            var args = new List<object?>(propertyKeys.Length);
             args.AddRange(propertyKeys);
             Bytecode.AddStep("propertyMap", args.ToArray());
-            return Wrap<S, IDictionary<string, E2>>(this);
+            return Wrap<TStart, IDictionary<string, TNewEnd>>(this);
         }
 
         /// <summary>
         ///     Adds the range step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Range<E2> (Scope scope, long low, long high)
+        public GraphTraversal<TStart, TNewEnd> Range<TNewEnd> (Scope scope, long low, long high)
         {
             Bytecode.AddStep("range", scope, low, high);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the range step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Range<E2> (long low, long high)
+        public GraphTraversal<TStart, TNewEnd> Range<TNewEnd> (long low, long high)
         {
             Bytecode.AddStep("range", low, high);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the read step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Read ()
+        public GraphTraversal<TStart, TEnd> Read ()
         {
             Bytecode.AddStep("read");
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the repeat step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Repeat (string loopName, ITraversal repeatTraversal)
+        public GraphTraversal<TStart, TEnd> Repeat (string loopName, ITraversal repeatTraversal)
         {
             Bytecode.AddStep("repeat", loopName, repeatTraversal);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the repeat step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Repeat (ITraversal repeatTraversal)
+        public GraphTraversal<TStart, TEnd> Repeat (ITraversal repeatTraversal)
         {
             Bytecode.AddStep("repeat", repeatTraversal);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the sack step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Sack<E2> ()
+        public GraphTraversal<TStart, TNewEnd> Sack<TNewEnd> ()
         {
             Bytecode.AddStep("sack");
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the sack step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Sack (IBiFunction sackOperator)
+        public GraphTraversal<TStart, TEnd> Sack (IBiFunction sackOperator)
         {
             Bytecode.AddStep("sack", sackOperator);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the sample step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Sample (Scope scope, int amountToSample)
+        public GraphTraversal<TStart, TEnd> Sample (Scope scope, int amountToSample)
         {
             Bytecode.AddStep("sample", scope, amountToSample);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the sample step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Sample (int amountToSample)
+        public GraphTraversal<TStart, TEnd> Sample (int amountToSample)
         {
             Bytecode.AddStep("sample", amountToSample);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the select step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, ICollection<E2>> Select<E2> (Column column)
+        public GraphTraversal<TStart, ICollection<TNewEnd>> Select<TNewEnd> (Column column)
         {
             Bytecode.AddStep("select", column);
-            return Wrap<S, ICollection<E2>>(this);
+            return Wrap<TStart, ICollection<TNewEnd>>(this);
         }
 
         /// <summary>
         ///     Adds the select step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Select<E2> (Pop pop, string selectKey)
+        public GraphTraversal<TStart, TNewEnd> Select<TNewEnd> (Pop pop, string? selectKey)
         {
             Bytecode.AddStep("select", pop, selectKey);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the select step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, IDictionary<string, E2>> Select<E2>(Pop pop, string selectKey1, string selectKey2,
-            params string[] otherSelectKeys)
+        public GraphTraversal<TStart, IDictionary<string, TNewEnd>> Select<TNewEnd>(Pop pop, string? selectKey1,
+            string? selectKey2, params string?[] otherSelectKeys)
         {
             if (otherSelectKeys == null) throw new ArgumentNullException(nameof(otherSelectKeys));
 
-            var args = new List<object>(3 + otherSelectKeys.Length) { pop, selectKey1, selectKey2 };
+            var args = new List<object?>(3 + otherSelectKeys.Length) { pop, selectKey1, selectKey2 };
             args.AddRange(otherSelectKeys);
             Bytecode.AddStep("select", args.ToArray());
-            return Wrap<S, IDictionary<string, E2>>(this);
+            return Wrap<TStart, IDictionary<string, TNewEnd>>(this);
         }
 
         /// <summary>
         ///     Adds the select step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Select<E2> (Pop pop, ITraversal keyTraversal)
+        public GraphTraversal<TStart, TNewEnd> Select<TNewEnd> (Pop pop, ITraversal keyTraversal)
         {
             Bytecode.AddStep("select", pop, keyTraversal);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the select step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Select<E2> (string selectKey)
+        public GraphTraversal<TStart, TNewEnd> Select<TNewEnd> (string? selectKey)
         {
             Bytecode.AddStep("select", selectKey);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the select step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, IDictionary<string, E2>> Select<E2>(string selectKey1, string selectKey2,
-            params string[] otherSelectKeys)
+        public GraphTraversal<TStart, IDictionary<string, TNewEnd>> Select<TNewEnd>(string? selectKey1,
+            string? selectKey2, params string?[] otherSelectKeys)
         {
             if (otherSelectKeys == null) throw new ArgumentNullException(nameof(otherSelectKeys));
 
-            var args = new List<object>(2 + otherSelectKeys.Length) { selectKey1, selectKey2 };
+            var args = new List<object?>(2 + otherSelectKeys.Length) { selectKey1, selectKey2 };
             args.AddRange(otherSelectKeys);
             Bytecode.AddStep("select", args.ToArray());
-            return Wrap<S, IDictionary<string, E2>>(this);
+            return Wrap<TStart, IDictionary<string, TNewEnd>>(this);
         }
 
         /// <summary>
         ///     Adds the select step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Select<E2> (ITraversal keyTraversal)
+        public GraphTraversal<TStart, TNewEnd> Select<TNewEnd> (ITraversal keyTraversal)
         {
             Bytecode.AddStep("select", keyTraversal);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the shortestPath step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Path> ShortestPath ()
+        public GraphTraversal<TStart, Path> ShortestPath ()
         {
             Bytecode.AddStep("shortestPath");
-            return Wrap<S, Path>(this);
+            return Wrap<TStart, Path>(this);
         }
 
         /// <summary>
         ///     Adds the sideEffect step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> SideEffect (IConsumer consumer)
+        public GraphTraversal<TStart, TEnd> SideEffect (IConsumer? consumer)
         {
             Bytecode.AddStep("sideEffect", consumer);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the sideEffect step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> SideEffect (ITraversal sideEffectTraversal)
+        public GraphTraversal<TStart, TEnd> SideEffect (ITraversal sideEffectTraversal)
         {
             Bytecode.AddStep("sideEffect", sideEffectTraversal);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the simplePath step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> SimplePath ()
+        public GraphTraversal<TStart, TEnd> SimplePath ()
         {
             Bytecode.AddStep("simplePath");
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the skip step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Skip<E2> (Scope scope, long skip)
+        public GraphTraversal<TStart, TNewEnd> Skip<TNewEnd> (Scope scope, long skip)
         {
             Bytecode.AddStep("skip", scope, skip);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the skip step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Skip<E2> (long skip)
+        public GraphTraversal<TStart, TNewEnd> Skip<TNewEnd> (long skip)
         {
             Bytecode.AddStep("skip", skip);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the store step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Store (string sideEffectKey)
+        public GraphTraversal<TStart, TEnd> Store (string sideEffectKey)
         {
             Bytecode.AddStep("store", sideEffectKey);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the subgraph step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Edge> Subgraph (string sideEffectKey)
+        public GraphTraversal<TStart, Edge> Subgraph (string sideEffectKey)
         {
             Bytecode.AddStep("subgraph", sideEffectKey);
-            return Wrap<S, Edge>(this);
+            return Wrap<TStart, Edge>(this);
         }
 
         /// <summary>
         ///     Adds the sum step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Sum<E2> ()
+        public GraphTraversal<TStart, TNewEnd> Sum<TNewEnd> ()
         {
             Bytecode.AddStep("sum");
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the sum step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Sum<E2> (Scope scope)
+        public GraphTraversal<TStart, TNewEnd> Sum<TNewEnd> (Scope scope)
         {
             Bytecode.AddStep("sum", scope);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the tail step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Tail<E2> ()
+        public GraphTraversal<TStart, TNewEnd> Tail<TNewEnd> ()
         {
             Bytecode.AddStep("tail");
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the tail step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Tail<E2> (Scope scope)
+        public GraphTraversal<TStart, TNewEnd> Tail<TNewEnd> (Scope scope)
         {
             Bytecode.AddStep("tail", scope);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the tail step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Tail<E2> (Scope scope, long limit)
+        public GraphTraversal<TStart, TNewEnd> Tail<TNewEnd> (Scope scope, long limit)
         {
             Bytecode.AddStep("tail", scope, limit);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the tail step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Tail<E2> (long limit)
+        public GraphTraversal<TStart, TNewEnd> Tail<TNewEnd> (long limit)
         {
             Bytecode.AddStep("tail", limit);
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the timeLimit step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> TimeLimit (long timeLimit)
+        public GraphTraversal<TStart, TEnd> TimeLimit (long timeLimit)
         {
             Bytecode.AddStep("timeLimit", timeLimit);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the times step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Times (int maxLoops)
+        public GraphTraversal<TStart, TEnd> Times (int maxLoops)
         {
             Bytecode.AddStep("times", maxLoops);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the to step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Vertex> To (Direction direction, params string[] edgeLabels)
+        public GraphTraversal<TStart, Vertex> To (Direction? direction, params string?[] edgeLabels)
         {
             if (edgeLabels == null) throw new ArgumentNullException(nameof(edgeLabels));
 
-            var args = new List<object>(1 + edgeLabels.Length) { direction };
+            var args = new List<object?>(1 + edgeLabels.Length) { direction };
             args.AddRange(edgeLabels);
             Bytecode.AddStep("to", args.ToArray());
-            return Wrap<S, Vertex>(this);
+            return Wrap<TStart, Vertex>(this);
         }
 
         /// <summary>
         ///     Adds the to step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> To (string toStepLabel)
+        public GraphTraversal<TStart, TEnd> To (string? toStepLabel)
         {
             Bytecode.AddStep("to", toStepLabel);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the to step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> To (ITraversal toVertex)
+        public GraphTraversal<TStart, TEnd> To (ITraversal toVertex)
         {
             Bytecode.AddStep("to", toVertex);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the to step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> To (Vertex toVertex)
+        public GraphTraversal<TStart, TEnd> To (Vertex? toVertex)
         {
             Bytecode.AddStep("to", toVertex);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the toE step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Edge> ToE (Direction direction, params string[] edgeLabels)
+        public GraphTraversal<TStart, Edge> ToE (Direction? direction, params string?[] edgeLabels)
         {
             if (edgeLabels == null) throw new ArgumentNullException(nameof(edgeLabels));
             
-            var args = new List<object>(1 + edgeLabels.Length) {direction};
+            var args = new List<object?>(1 + edgeLabels.Length) {direction};
             args.AddRange(edgeLabels);
             Bytecode.AddStep("toE", args.ToArray());
-            return Wrap<S, Edge>(this);
+            return Wrap<TStart, Edge>(this);
         }
 
         /// <summary>
         ///     Adds the toV step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, Vertex> ToV (Direction direction)
+        public GraphTraversal<TStart, Vertex> ToV (Direction? direction)
         {
             Bytecode.AddStep("toV", direction);
-            return Wrap<S, Vertex>(this);
+            return Wrap<TStart, Vertex>(this);
         }
 
         /// <summary>
         ///     Adds the tree step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Tree<E2> ()
+        public GraphTraversal<TStart, TNewEnd> Tree<TNewEnd> ()
         {
             Bytecode.AddStep("tree");
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the tree step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Tree (string sideEffectKey)
+        public GraphTraversal<TStart, TEnd> Tree (string sideEffectKey)
         {
             Bytecode.AddStep("tree", sideEffectKey);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the unfold step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Unfold<E2> ()
+        public GraphTraversal<TStart, TNewEnd> Unfold<TNewEnd> ()
         {
             Bytecode.AddStep("unfold");
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the union step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Union<E2> (params ITraversal[] unionTraversals)
+        public GraphTraversal<TStart, TNewEnd> Union<TNewEnd> (params ITraversal[] unionTraversals)
         {
             if (unionTraversals == null) throw new ArgumentNullException(nameof(unionTraversals));
             
             var args = new List<object>(unionTraversals.Length);
             args.AddRange(unionTraversals);
             Bytecode.AddStep("union", args.ToArray());
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the until step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Until (IPredicate untilPredicate)
+        public GraphTraversal<TStart, TEnd> Until (IPredicate untilPredicate)
         {
             Bytecode.AddStep("until", untilPredicate);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the until step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Until (ITraversal untilTraversal)
+        public GraphTraversal<TStart, TEnd> Until (ITraversal untilTraversal)
         {
             Bytecode.AddStep("until", untilTraversal);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the value step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Value<E2> ()
+        public GraphTraversal<TStart, TNewEnd> Value<TNewEnd> ()
         {
             Bytecode.AddStep("value");
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the valueMap step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, IDictionary<TKey, TValue>> ValueMap<TKey, TValue> (params string[] propertyKeys)
+        public GraphTraversal<TStart, IDictionary<TKey, TValue>> ValueMap<TKey, TValue> (params string?[] propertyKeys)
         {
             if (propertyKeys == null) throw new ArgumentNullException(nameof(propertyKeys));
             
-            var args = new List<object>(propertyKeys.Length);
+            var args = new List<object?>(propertyKeys.Length);
             args.AddRange(propertyKeys);
             Bytecode.AddStep("valueMap", args.ToArray());
-            return Wrap<S, IDictionary<TKey, TValue>>(this);
+            return Wrap<TStart, IDictionary<TKey, TValue>>(this);
         }
 
         /// <summary>
         ///     Adds the valueMap step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, IDictionary<TKey, TValue>> ValueMap<TKey, TValue>(bool includeTokens,
-            params string[] propertyKeys)
+        public GraphTraversal<TStart, IDictionary<TKey, TValue>> ValueMap<TKey, TValue>(bool includeTokens,
+            params string?[] propertyKeys)
         {
             if (propertyKeys == null) throw new ArgumentNullException(nameof(propertyKeys));
 
-            var args = new List<object>(1 + propertyKeys.Length) { includeTokens };
+            var args = new List<object?>(1 + propertyKeys.Length) { includeTokens };
             args.AddRange(propertyKeys);
             Bytecode.AddStep("valueMap", args.ToArray());
-            return Wrap<S, IDictionary<TKey, TValue>>(this);
+            return Wrap<TStart, IDictionary<TKey, TValue>>(this);
         }
 
         /// <summary>
         ///     Adds the values step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E2> Values<E2> (params string[] propertyKeys)
+        public GraphTraversal<TStart, TNewEnd> Values<TNewEnd> (params string?[] propertyKeys)
         {
             if (propertyKeys == null) throw new ArgumentNullException(nameof(propertyKeys));
             
-            var args = new List<object>(propertyKeys.Length);
+            var args = new List<object?>(propertyKeys.Length);
             args.AddRange(propertyKeys);
             Bytecode.AddStep("values", args.ToArray());
-            return Wrap<S, E2>(this);
+            return Wrap<TStart, TNewEnd>(this);
         }
 
         /// <summary>
         ///     Adds the where step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Where (P predicate)
+        public GraphTraversal<TStart, TEnd> Where (P predicate)
         {
             Bytecode.AddStep("where", predicate);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the where step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Where (string startKey, P predicate)
+        public GraphTraversal<TStart, TEnd> Where (string startKey, P predicate)
         {
             Bytecode.AddStep("where", startKey, predicate);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the where step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Where (ITraversal whereTraversal)
+        public GraphTraversal<TStart, TEnd> Where (ITraversal whereTraversal)
         {
             Bytecode.AddStep("where", whereTraversal);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the with step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> With (string key)
+        public GraphTraversal<TStart, TEnd> With (string key)
         {
             Bytecode.AddStep("with", key);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the with step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> With (string key, object value)
+        public GraphTraversal<TStart, TEnd> With (string key, object? value)
         {
             Bytecode.AddStep("with", key, value);
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
         /// <summary>
         ///     Adds the write step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public GraphTraversal<S, E> Write ()
+        public GraphTraversal<TStart, TEnd> Write ()
         {
             Bytecode.AddStep("write");
-            return Wrap<S, E>(this);
+            return Wrap<TStart, TEnd>(this);
         }
 
 
         /// <summary>
         /// Make a copy of a traversal that is reset for iteration.
         /// </summary>
-        public GraphTraversal<S, E> Clone()
+        public GraphTraversal<TStart, TEnd> Clone()
         {
-            return new GraphTraversal<S, E>(TraversalStrategies, new Bytecode(Bytecode));
+            return new GraphTraversal<TStart, TEnd>(TraversalStrategies, new Bytecode(Bytecode));
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
index 6f18bc2..218fb7b 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs
@@ -38,7 +38,7 @@
     /// </summary>
     public class GraphTraversalSource
     {
-        private readonly IRemoteConnection _connection;
+        private readonly IRemoteConnection? _connection;
 
         public bool IsSessionBound => _connection is { IsSessionBound: true };
         
@@ -89,7 +89,7 @@
             return With(key, true);
         }
 
-        public GraphTraversalSource With(string key, object value)
+        public GraphTraversalSource With(string key, object? value)
         {
             var optionsStrategyInst = Bytecode.SourceInstructions.Find(
                 inst => inst.OperatorName == "withStrategies" && inst.Arguments[0] is OptionsStrategy);
@@ -102,7 +102,7 @@
                 return WithStrategies(optionsStrategy);
             }
 
-            optionsStrategy = optionsStrategyInst.Arguments[0];
+            optionsStrategy = optionsStrategyInst.Arguments[0]!;
             optionsStrategy.Configuration[key] = value;
             return new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                 new Bytecode(Bytecode));
@@ -125,7 +125,7 @@
             return source;
         }
 
-        public GraphTraversalSource WithSack(object initialValue)
+        public GraphTraversalSource WithSack(object? initialValue)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -133,7 +133,7 @@
             return source;
         }
 
-        public GraphTraversalSource WithSack(object initialValue, IBinaryOperator mergeOperator)
+        public GraphTraversalSource WithSack(object? initialValue, IBinaryOperator? mergeOperator)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -141,7 +141,7 @@
             return source;
         }
 
-        public GraphTraversalSource WithSack(object initialValue, IUnaryOperator splitOperator)
+        public GraphTraversalSource WithSack(object? initialValue, IUnaryOperator? splitOperator)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -149,7 +149,8 @@
             return source;
         }
 
-        public GraphTraversalSource WithSack(object initialValue, IUnaryOperator splitOperator, IBinaryOperator mergeOperator)
+        public GraphTraversalSource WithSack(object? initialValue, IUnaryOperator? splitOperator,
+            IBinaryOperator? mergeOperator)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -157,7 +158,7 @@
             return source;
         }
 
-        public GraphTraversalSource WithSack(ISupplier initialValue)
+        public GraphTraversalSource WithSack(ISupplier? initialValue)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -165,7 +166,7 @@
             return source;
         }
 
-        public GraphTraversalSource WithSack(ISupplier initialValue, IBinaryOperator mergeOperator)
+        public GraphTraversalSource WithSack(ISupplier? initialValue, IBinaryOperator? mergeOperator)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -173,7 +174,7 @@
             return source;
         }
 
-        public GraphTraversalSource WithSack(ISupplier initialValue, IUnaryOperator splitOperator)
+        public GraphTraversalSource WithSack(ISupplier? initialValue, IUnaryOperator? splitOperator)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -181,7 +182,8 @@
             return source;
         }
 
-        public GraphTraversalSource WithSack(ISupplier initialValue, IUnaryOperator splitOperator, IBinaryOperator mergeOperator)
+        public GraphTraversalSource WithSack(ISupplier? initialValue, IUnaryOperator? splitOperator,
+            IBinaryOperator? mergeOperator)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -189,7 +191,7 @@
             return source;
         }
 
-        public GraphTraversalSource WithSideEffect(string key, object initialValue)
+        public GraphTraversalSource WithSideEffect(string? key, object? initialValue)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -197,7 +199,7 @@
             return source;
         }
 
-        public GraphTraversalSource WithSideEffect(string key, object initialValue, IBinaryOperator reducer)
+        public GraphTraversalSource WithSideEffect(string? key, object? initialValue, IBinaryOperator reducer)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -205,7 +207,7 @@
             return source;
         }
 
-        public GraphTraversalSource WithSideEffect(string key, ISupplier initialValue)
+        public GraphTraversalSource WithSideEffect(string? key, ISupplier? initialValue)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -213,7 +215,7 @@
             return source;
         }
 
-        public GraphTraversalSource WithSideEffect(string key, ISupplier initialValue, IBinaryOperator reducer)
+        public GraphTraversalSource WithSideEffect(string? key, ISupplier? initialValue, IBinaryOperator? reducer)
         {
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
@@ -233,20 +235,20 @@
             return source;
         }
 
-        public GraphTraversalSource WithoutStrategies(params Type[] traversalStrategyClasses)
+        public GraphTraversalSource WithoutStrategies(params Type?[] traversalStrategyClasses)
         {
             if (traversalStrategyClasses == null) throw new ArgumentNullException(nameof(traversalStrategyClasses));
             
             var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies),
                                                   new Bytecode(Bytecode));
-            var args = new List<object>(traversalStrategyClasses.Length);
+            var args = new List<object?>(traversalStrategyClasses.Length);
             args.AddRange(traversalStrategyClasses);
             source.Bytecode.AddSource("withoutStrategies", args.ToArray());
             return source;
         }
 
         [Obsolete("Use the Bindings class instead.", false)]
-        public GraphTraversalSource WithBindings(object bindings)
+        public GraphTraversalSource WithBindings(object? bindings)
         {
             return this;
         }
@@ -277,35 +279,35 @@
                 throw new InvalidOperationException(
                     "This GraphTraversalSource is already bound to a transaction - child transactions are not supported");
             }
-            return _connection.Tx(this);
+            return _connection!.Tx(this);
         }
 
         /// <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)
+        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));
+            return WithStrategies(new VertexProgramStrategy(graphComputer, workers, persist, result, vertices, edges,
+                configuration));
         }
 
-
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the E step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<Edge, Edge> E(params object[] edgesIds)
+        public GraphTraversal<Edge, Edge> E(params object?[]? edgesIds)
         {
             var traversal = new GraphTraversal<Edge, Edge>(TraversalStrategies, new Bytecode(Bytecode));
             if (edgesIds == null)
             {
-                traversal.Bytecode.AddStep("E", new object[] { null });
+                traversal.Bytecode.AddStep("E", new object?[] { null });
             }
             else
             {
-                var args = new List<object>(edgesIds.Length);
+                var args = new List<object?>(edgesIds.Length);
                 args.AddRange(edgesIds);
                 traversal.Bytecode.AddStep("E", args.ToArray());
             }
@@ -316,16 +318,16 @@
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the V step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<Vertex, Vertex> V(params object[] vertexIds)
+        public GraphTraversal<Vertex, Vertex> V(params object?[]? vertexIds)
         {
             var traversal = new GraphTraversal<Vertex, Vertex>(TraversalStrategies, new Bytecode(Bytecode));
             if (vertexIds == null)
             {
-                traversal.Bytecode.AddStep("V", new object[] { null });
+                traversal.Bytecode.AddStep("V", new object?[] { null });
             }
             else
             {
-                var args = new List<object>(vertexIds.Length);
+                var args = new List<object?>(vertexIds.Length);
                 args.AddRange(vertexIds);
                 traversal.Bytecode.AddStep("V", args.ToArray());
             }
@@ -358,7 +360,7 @@
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the mergeE step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<Edge, Edge> MergeE(IDictionary<object,object> m)
+        public GraphTraversal<Edge, Edge> MergeE(IDictionary<object,object>? m)
         {
             var traversal = new GraphTraversal<Edge, Edge>(TraversalStrategies, new Bytecode(Bytecode));
             traversal.Bytecode.AddStep("mergeE", m);
@@ -369,7 +371,7 @@
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the mergeE step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<Edge, Edge> MergeE(ITraversal t)
+        public GraphTraversal<Edge, Edge> MergeE(ITraversal? t)
         {
             var traversal = new GraphTraversal<Edge, Edge>(TraversalStrategies, new Bytecode(Bytecode));
             traversal.Bytecode.AddStep("mergeE", t);
@@ -413,7 +415,7 @@
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the mergeV step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<Vertex, Vertex> MergeV(IDictionary<object,object> m)
+        public GraphTraversal<Vertex, Vertex> MergeV(IDictionary<object,object>? m)
         {
             var traversal = new GraphTraversal<Vertex, Vertex>(TraversalStrategies, new Bytecode(Bytecode));
             traversal.Bytecode.AddStep("mergeV", m);
@@ -424,7 +426,7 @@
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the mergeV step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<Vertex, Vertex> MergeV(ITraversal t)
+        public GraphTraversal<Vertex, Vertex> MergeV(ITraversal? t)
         {
             var traversal = new GraphTraversal<Vertex, Vertex>(TraversalStrategies, new Bytecode(Bytecode));
             traversal.Bytecode.AddStep("mergeV", t);
@@ -435,19 +437,19 @@
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the inject step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<S, S> Inject<S>(params S[] starts)
+        public GraphTraversal<TStart, TStart> Inject<TStart>(params TStart?[]? starts)
         {
-            var traversal = new GraphTraversal<S, S>(TraversalStrategies, new Bytecode(Bytecode));
+            var traversal = new GraphTraversal<TStart, TStart>(TraversalStrategies, new Bytecode(Bytecode));
 
             // null starts is treated as g.inject(null) meaning inject a single null traverser
             if (starts == null)
             {
-                traversal.Bytecode.AddStep("inject", new object[] { null });
+                traversal.Bytecode.AddStep("inject", new object?[] { null });
             }
             else
             {
-                var args = new List<object>(starts.Length);
-                args.AddRange(starts.Cast<object>());
+                var args = new List<object?>(starts.Length);
+                args.AddRange(starts.Cast<object?>());
                 traversal.Bytecode.AddStep("inject", args.ToArray());
             }
 
@@ -458,10 +460,10 @@
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the io step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<S, S> Io<S>(string file)
+        public GraphTraversal<TStart, TStart> Io<TStart>(string file)
         {
-            var traversal = new GraphTraversal<S, S>(TraversalStrategies, new Bytecode(Bytecode));
-                traversal.Bytecode.AddStep("io", file);
+            var traversal = new GraphTraversal<TStart, TStart>(TraversalStrategies, new Bytecode(Bytecode));
+            traversal.Bytecode.AddStep("io", file);
             return traversal;
         }
 
@@ -469,9 +471,9 @@
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the call step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<S, S> Call<S>()
+        public GraphTraversal<TStart, TStart> Call<TStart>()
         {
-            var traversal = new GraphTraversal<S, S>(TraversalStrategies, new Bytecode(Bytecode));
+            var traversal = new GraphTraversal<TStart, TStart>(TraversalStrategies, new Bytecode(Bytecode));
             traversal.Bytecode.AddStep("call");
             return traversal;
         }
@@ -480,9 +482,9 @@
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the call step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<S, S> Call<S>(string service)
+        public GraphTraversal<TStart, TStart> Call<TStart>(string? service)
         {
-            var traversal = new GraphTraversal<S, S>(TraversalStrategies, new Bytecode(Bytecode));
+            var traversal = new GraphTraversal<TStart, TStart>(TraversalStrategies, new Bytecode(Bytecode));
             traversal.Bytecode.AddStep("call", service);
             return traversal;
         }
@@ -491,9 +493,9 @@
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the call step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<S, S> Call<S>(string service, IDictionary<object,object> m)
+        public GraphTraversal<TStart, TStart> Call<TStart>(string? service, IDictionary<object, object>? m)
         {
-            var traversal = new GraphTraversal<S, S>(TraversalStrategies, new Bytecode(Bytecode));
+            var traversal = new GraphTraversal<TStart, TStart>(TraversalStrategies, new Bytecode(Bytecode));
             traversal.Bytecode.AddStep("call", service, m);
             return traversal;
         }
@@ -502,9 +504,9 @@
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the call step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<S, S> Call<S>(string service, ITraversal t)
+        public GraphTraversal<TStart, TStart> Call<TStart>(string? service, ITraversal? t)
         {
-            var traversal = new GraphTraversal<S, S>(TraversalStrategies, new Bytecode(Bytecode));
+            var traversal = new GraphTraversal<TStart, TStart>(TraversalStrategies, new Bytecode(Bytecode));
             traversal.Bytecode.AddStep("call", service, t);
             return traversal;
         }
@@ -513,14 +515,14 @@
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the call step to that
         ///     traversal.
         /// </summary>
-        public GraphTraversal<S, S> Call<S>(string service, IDictionary<object,object> m, ITraversal t)
+        public GraphTraversal<TStart, TStart> Call<TStart>(string? service, IDictionary<object, object>? m,
+            ITraversal? t)
         {
-            var traversal = new GraphTraversal<S, S>(TraversalStrategies, new Bytecode(Bytecode));
+            var traversal = new GraphTraversal<TStart, TStart>(TraversalStrategies, new Bytecode(Bytecode));
             traversal.Bytecode.AddStep("call", service, m, t);
             return traversal;
         }
 
-
     }
     
 #pragma warning restore 1591
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversal.cs
index f0c682d..17874b5 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversal.cs
@@ -48,7 +48,7 @@
         /// <summary>
         ///     Gets or sets the <see cref="Traverser" />'s of this traversal that hold the results of the traversal.
         /// </summary>
-        IEnumerable<Traverser> Traversers { get; set; }
+        IEnumerable<Traverser>? Traversers { get; set; }
 
         /// <summary>
         ///     Iterates all <see cref="Traverser" /> instances in the traversal.
@@ -60,13 +60,13 @@
     /// <summary>
     ///     A traversal represents a directed walk over a graph.
     /// </summary>
-    public interface ITraversal<S, E> : ITraversal, IEnumerator<E>
+    public interface ITraversal<TStart, TEnd> : ITraversal, IEnumerator<TEnd?>
     {
         /// <summary>
         ///     Gets the next result from the traversal.
         /// </summary>
         /// <returns>The result.</returns>
-        E Next();
+        TEnd? Next();
 
         /// <summary>
         ///     Determines if the traversal contains any additional results for iteration.
@@ -79,13 +79,13 @@
         /// </summary>
         /// <param name="amount">The number of results to get.</param>
         /// <returns>The n-results.</returns>
-        IEnumerable<E> Next(int amount);
+        IEnumerable<TEnd?> Next(int amount);
 
         /// <summary>
         ///     Iterates all <see cref="Traverser" /> instances in the traversal.
         /// </summary>
         /// <returns>The fully drained traversal.</returns>
-        new ITraversal<S, E> Iterate();
+        new ITraversal<TStart, TEnd> Iterate();
 
         /// <summary>
         ///     Gets the next <see cref="Traverser" />.
@@ -97,13 +97,13 @@
         ///     Puts all the results into a <see cref="IList{T}" />.
         /// </summary>
         /// <returns>The results in a list.</returns>
-        IList<E> ToList();
+        IList<TEnd?> ToList();
 
         /// <summary>
         ///     Puts all the results into a <see cref="ISet{T}" />.
         /// </summary>
         /// <returns>The results in a set.</returns>
-        ISet<E> ToSet();
+        ISet<TEnd?> ToSet();
 
         /// <summary>
         ///     Starts a promise to execute a function on the current traversal that will be completed in the future.
@@ -112,7 +112,7 @@
         /// <param name="callback">The function to execute on the current traversal.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <returns>The result of the executed <paramref name="callback" />.</returns>
-        Task<TReturn> Promise<TReturn>(Func<ITraversal<S, E>, TReturn> callback,
+        Task<TReturn> Promise<TReturn>(Func<ITraversal<TStart, TEnd>, TReturn> callback,
             CancellationToken cancellationToken = default);
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversalStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversalStrategy.cs
index 45a0b97..20b3bc0 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversalStrategy.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/ITraversalStrategy.cs
@@ -36,13 +36,13 @@
         ///     Applies the strategy to the given <see cref="ITraversal" />.
         /// </summary>
         /// <param name="traversal">The <see cref="ITraversal" /> the strategy should be applied to.</param>
-        void Apply<S, E>(ITraversal<S, E> traversal);
+        void Apply<TStart, TEnd>(ITraversal<TStart, TEnd> traversal);
 
         /// <summary>
         ///     Applies the strategy to the given <see cref="ITraversal" /> asynchronously.
         /// </summary>
         /// <param name="traversal">The <see cref="ITraversal" /> the strategy should be applied to.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
-        Task ApplyAsync<S, E>(ITraversal<S, E> traversal, CancellationToken cancellationToken = default);
+        Task ApplyAsync<TStart, TEnd>(ITraversal<TStart, TEnd> traversal, CancellationToken cancellationToken = default);
     }
 }
\ 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 f6453fe..cf9cd0c 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Instruction.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Instruction.cs
@@ -36,10 +36,10 @@
         /// </summary>
         /// <param name="operatorName">The name of the operator.</param>
         /// <param name="arguments">The arguments.</param>
-        public Instruction(string operatorName, params dynamic[] arguments)
+        public Instruction(string operatorName, params dynamic?[] arguments)
         {
-            OperatorName = operatorName;
-            Arguments = arguments;
+            OperatorName = operatorName ?? throw new ArgumentNullException(nameof(operatorName));
+            Arguments = arguments ?? throw new ArgumentNullException(nameof(arguments));
         }
 
         /// <summary>
@@ -50,7 +50,7 @@
         /// <summary>
         ///     Gets the arguments.
         /// </summary>
-        public dynamic[] Arguments { get; }
+        public dynamic?[] Arguments { get; }
 
         /// <summary>
         ///     String representation of the <see cref="Instruction"/>.
@@ -61,7 +61,7 @@
         }
 
         /// <inheritdoc />
-        public bool Equals(Instruction other)
+        public bool Equals(Instruction? other)
         {
             if (ReferenceEquals(null, other)) return false;
             if (ReferenceEquals(this, other)) return true;
@@ -69,7 +69,7 @@
         }
 
         /// <inheritdoc />
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             if (ReferenceEquals(null, obj)) return false;
             if (ReferenceEquals(this, obj)) return true;
@@ -83,15 +83,10 @@
             unchecked
             {
                 var hash = 19;
-                if (OperatorName != null)
-                {
-                    hash = hash * 397 + OperatorName.GetHashCode();
-                }
+                hash = hash * 397 + OperatorName.GetHashCode();
 
-                if (Arguments != null)
-                {
-                    hash = Arguments.Aggregate(hash, (current, value) => current * 31 + value.GetHashCode());
-                }
+                hash = Arguments.Aggregate(hash,
+                    (current, value) => current * 31 + (value == null ? 0 : value.GetHashCode()));
 
                 return hash;
             }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/NamingConversions.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/NamingConversions.cs
deleted file mode 100644
index a650dc5..0000000
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/NamingConversions.cs
+++ /dev/null
@@ -1,91 +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.Process.Traversal
-{
-    internal static class NamingConversions
-    {
-        /// <summary>
-        ///     Gets the Java name equivalent for a given enum value
-        /// </summary>
-        internal static string GetEnumJavaName(string typeName, string value)
-        {
-            var key = $"{typeName}.{value}";
-            string javaName;
-            if (!CSharpToJavaEnums.TryGetValue(key, out javaName))
-            {
-                throw new KeyNotFoundException($"Java name for {key} not found");
-            }
-            return javaName;
-        }
-
-        internal static readonly IDictionary<string, string> CSharpToJavaEnums = new Dictionary<string, string>
-        {
-            {"Barrier.NormSack", "normSack"},
-            {"Cardinality.List", "list"},
-            {"Cardinality.Set", "set"},
-            {"Cardinality.Single", "single"},
-            {"Column.Keys", "keys"},
-            {"Column.Values", "values"},
-            {"Direction.Both", "BOTH"},
-            {"Direction.In", "IN"},
-            {"Direction.Out", "OUT"},
-            {"GraphSONVersion.V1_0", "V1_0"},
-            {"GraphSONVersion.V2_0", "V2_0"},
-            {"GraphSONVersion.V3_0", "V3_0"},
-            {"GryoVersion.V1_0", "V1_0"},
-            {"GryoVersion.V3_0", "V3_0"},
-            {"Operator.AddAll", "addAll"},
-            {"Operator.And", "and"},
-            {"Operator.Assign", "assign"},
-            {"Operator.Div", "div"},
-            {"Operator.Max", "max"},
-            {"Operator.Min", "min"},
-            {"Operator.Minus", "minus"},
-            {"Operator.Mult", "mult"},
-            {"Operator.Or", "or"},
-            {"Operator.Sum", "sum"},
-            {"Operator.SumLong", "sumLong"},
-            {"Order.Decr", "decr"},
-            {"Order.Incr", "incr"},
-            {"Order.Shuffle", "shuffle"},
-            {"Order.Asc", "asc"},
-            {"Order.Desc", "desc"},
-            {"Pick.Any", "any"},
-            {"Pick.None", "none"},
-            {"Pop.All", "all"},
-            {"Pop.First", "first"},
-            {"Pop.Last", "last"},
-            {"Pop.Mixed", "mixed"},
-            {"Scope.Global", "global"},
-            {"Scope.Local", "local"},
-            {"T.Id", "id"},
-            {"T.Key", "key"},
-            {"T.Label", "label"},
-            {"T.Value", "value"}
-
-        };
-    }
-}
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/P.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/P.cs
index 733352b..2e4e2b3 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/P.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/P.cs
@@ -41,7 +41,7 @@
         /// <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)
+        public P(string operatorName, dynamic? value, P? other = null)
         {
             OperatorName = operatorName;
             Value = value;
@@ -56,12 +56,12 @@
         /// <summary>
         ///     Gets the value of the predicate.
         /// </summary>
-        public dynamic Value { get; }
+        public dynamic? Value { get; }
 
         /// <summary>
         ///     Gets an optional other predicate that is used as an argument for this predicate.
         /// </summary>
-        public P Other { get; }
+        public P? Other { get; }
 
         /// <summary>
         ///     Returns a composed predicate that represents a logical AND of this predicate and another.
@@ -83,86 +83,86 @@
             return new P("or", this, otherPredicate);
         }
 
-        public static P Between(params object[] args)
+        public static P Between(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("between", value);
         }
 
-        public static P Eq(params object[] args)
+        public static P Eq(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("eq", value);
         }
 
-        public static P Gt(params object[] args)
+        public static P Gt(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("gt", value);
         }
 
-        public static P Gte(params object[] args)
+        public static P Gte(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("gte", value);
         }
 
-        public static P Inside(params object[] args)
+        public static P Inside(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("inside", value);
         }
 
-        public static P Lt(params object[] args)
+        public static P Lt(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("lt", value);
         }
 
-        public static P Lte(params object[] args)
+        public static P Lte(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("lte", value);
         }
 
-        public static P Neq(params object[] args)
+        public static P Neq(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("neq", value);
         }
 
-        public static P Not(params object[] args)
+        public static P Not(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("not", value);
         }
 
-        public static P Outside(params object[] args)
+        public static P Outside(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("outside", value);
         }
 
-        public static P Test(params object[] args)
+        public static P Test(params object[]? args)
         {
-            var value = args != null && args.Length == 1 ? args[0] : args;
+            var value = args is { Length: 1 } ? args[0] : args;
             return new P("test", value);
         }
 
-        public static P Within(params object[] args)
+        public static P Within(params object[]? args)
         {
-            var x = args != null && args.Length == 1 && args[0] is ICollection collection ? collection : args;
+            var x = args is { Length: 1 } && args[0] is ICollection collection ? collection : args;
             return new P("within", ToGenericList(x));
         }
 
-        public static P Without(params object[] args)
+        public static P Without(params object[]? args)
         {
-            var x = args != null && args.Length == 1 && args[0] is ICollection collection ? collection : args;
+            var x = args is { Length: 1 } && args[0] is ICollection collection ? collection : args;
             return new P("without", ToGenericList(x));
         }
 
 
-        private static List<object> ToGenericList(IEnumerable collection)
+        private static List<object> ToGenericList(IEnumerable? collection)
         {
             return collection?.Cast<object>().ToList() ?? Enumerable.Empty<object>().ToList();
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/AbstractTraversalStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/AbstractTraversalStrategy.cs
index 7170aa7..1c7376d 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/AbstractTraversalStrategy.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/AbstractTraversalStrategy.cs
@@ -84,10 +84,10 @@
         /// <summary>
         ///     Gets the configuration of the strategy.
         /// </summary>
-        public Dictionary<string, dynamic> Configuration { get; } = new Dictionary<string, dynamic>();
+        public Dictionary<string, dynamic?> Configuration { get; } = new();
 
         /// <inheritdoc />
-        public bool Equals(AbstractTraversalStrategy other)
+        public bool Equals(AbstractTraversalStrategy? other)
         {
             if (ReferenceEquals(null, other)) return false;
             if (ReferenceEquals(this, other)) return true;
@@ -95,18 +95,18 @@
         }
 
         /// <inheritdoc />
-        public virtual void Apply<S, E>(ITraversal<S, E> traversal)
+        public virtual void Apply<TStart, TEnd>(ITraversal<TStart, TEnd> traversal)
         {
         }
 
         /// <inheritdoc />
-        public virtual Task ApplyAsync<S, E>(ITraversal<S, E> traversal, CancellationToken cancellationToken = default)
+        public virtual Task ApplyAsync<TStart, TEnd>(ITraversal<TStart, TEnd> traversal, CancellationToken cancellationToken = default)
         {
             return Task.CompletedTask;
         }
 
         /// <inheritdoc />
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             if (ReferenceEquals(null, obj)) return false;
             if (ReferenceEquals(this, obj)) return true;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/HaltedTraverserStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/HaltedTraverserStrategy.cs
index 6ae8876..ffa38fc 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/HaltedTraverserStrategy.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/HaltedTraverserStrategy.cs
@@ -32,7 +32,7 @@
         {
         }
 
-        public HaltedTraverserStrategy(string haltedTraverserFactoryName = null)
+        public HaltedTraverserStrategy(string? haltedTraverserFactoryName = null)
             : this()
         {
             if (haltedTraverserFactoryName != null)
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/PartitionStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/PartitionStrategy.cs
index 8c59ad4..34f7b55 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/PartitionStrategy.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/PartitionStrategy.cs
@@ -49,8 +49,8 @@
         /// </param>
         /// <param name="readPartitions">Specifies the partition of the graph to read from.</param>
         /// <param name="includeMetaProperties">Set to true if vertex properties should get assigned to partitions.</param>
-        public PartitionStrategy(string partitionKey = null, string writePartition = null,
-            IEnumerable<string> readPartitions = null, bool? includeMetaProperties = null)
+        public PartitionStrategy(string? partitionKey = null, string? writePartition = null,
+            IEnumerable<string>? readPartitions = null, bool? includeMetaProperties = null)
             : this()
         {
             if (partitionKey != null)
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/SubgraphStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/SubgraphStrategy.cs
index af312d6..141b851 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/SubgraphStrategy.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/SubgraphStrategy.cs
@@ -44,8 +44,8 @@
         /// <param name="edges">Constrains edges for the <see cref="ITraversal" />.</param>
         /// <param name="vertexProperties">Constrains vertex properties for the <see cref="ITraversal" />.</param>
         /// <param name="checkAdjacentVertices">Determines if filters are applied to the adjacent vertices of an edge.</param>
-        public SubgraphStrategy(ITraversal vertices = null, ITraversal edges = null,
-            ITraversal vertexProperties = null, bool? checkAdjacentVertices = null)
+        public SubgraphStrategy(ITraversal? vertices = null, ITraversal? edges = null,
+            ITraversal? vertexProperties = null, bool? checkAdjacentVertices = null)
             : this()
         {
             if (vertices != null)
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/VertexProgramStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/VertexProgramStrategy.cs
index 17bfbaa..149dfe7 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/VertexProgramStrategy.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Decoration/VertexProgramStrategy.cs
@@ -35,9 +35,9 @@
         {
         }
 
-        public VertexProgramStrategy(string graphComputer = null, int? workers = null, string persist = null,
-            string result = null, ITraversal vertices = null, ITraversal edges = null,
-            Dictionary<string, dynamic> configuration = null)
+        public VertexProgramStrategy(string? graphComputer = null, int? workers = null, string? persist = null,
+            string? result = null, ITraversal? vertices = null, ITraversal? edges = null,
+            Dictionary<string, dynamic>? configuration = null)
             : this()
         {
             if (graphComputer != null)
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Optimization/ProductiveByStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Optimization/ProductiveByStrategy.cs
index 1586580..e989f48 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Optimization/ProductiveByStrategy.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Optimization/ProductiveByStrategy.cs
@@ -43,7 +43,7 @@
         ///     Initializes a new instance of the <see cref="ProductiveByStrategy" /> class.
         /// </summary>
         /// <param name="productiveKeys">Specifies keys that will always be productive.</param>
-        public ProductiveByStrategy(IEnumerable<object> productiveKeys = null)
+        public ProductiveByStrategy(IEnumerable<object>? productiveKeys = null)
             : this()
         {
             if (productiveKeys != null)
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Verification/ReservedKeysVerificationStrategy.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Verification/ReservedKeysVerificationStrategy.cs
index eccae0d..204f9d8 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Verification/ReservedKeysVerificationStrategy.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Strategy/Verification/ReservedKeysVerificationStrategy.cs
@@ -47,7 +47,7 @@
         /// <param name="throwException">Throw an exception if a reserved key is used.</param>
         /// <param name="keys">List of keys to define as reserved. If not set then the defaults are used.</param>
         public ReservedKeysVerificationStrategy(bool logWarning = false, bool throwException = false,
-            List<string> keys = null)
+            List<string>? keys = null)
             : this()
         {
             Configuration["logWarning"] = logWarning;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs
index 2bf4968..9a97d1a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/TextP.cs
@@ -41,7 +41,7 @@
         /// <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)
+        public TextP(string operatorName, string value, P? other = null) : base(operatorName, value, other)
         {
         }
 
@@ -86,11 +86,6 @@
             return new TextP("notRegex", value);
         }
 
-        private static T[] ToGenericArray<T>(ICollection<T> collection)
-        {
-            return collection?.ToArray() ?? new T[0];
-        }
-
         /// <inheritdoc />
         public override string ToString()
         {
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Translator/GroovyTranslator.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Translator/GroovyTranslator.cs
index 867c719..98dc5c4 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Translator/GroovyTranslator.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Translator/GroovyTranslator.cs
@@ -107,7 +107,7 @@
             return $".{step.OperatorName}({TranslateArguments(step.Arguments)})";

         }

         

-        private string TranslateWithArguments(dynamic[] arguments)

+        private string TranslateWithArguments(dynamic?[] arguments)

         {

             if (arguments[0] == WithOptions.Tokens)

             {

@@ -138,10 +138,10 @@
             { WithOptions.Map, "WithOptions.map" }

         };

 

-        private string TranslateArguments(IEnumerable<object> arguments) =>

+        private string TranslateArguments(IEnumerable<object?> arguments) =>

             string.Join(", ", arguments.Select(TranslateArgument));

 

-        private string TranslateArgument(object argument)

+        private string TranslateArgument(object? argument)

         {

             return argument switch

             {

@@ -157,7 +157,7 @@
                 IEnumerable e => TranslateCollection(e),

                 ITraversal t => TranslateTraversal(t),

                 AbstractTraversalStrategy strategy => TranslateStrategy(strategy),

-                _ => Convert.ToString(argument, CultureInfo.InvariantCulture)

+                _ => Convert.ToString(argument, CultureInfo.InvariantCulture)!

             };

         }

         

diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Traverser.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Traverser.cs
index 573e57f..6c241ef 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Traverser.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Traverser.cs
@@ -33,7 +33,7 @@
         /// </summary>
         /// <param name="obj">The object of the traverser.</param>
         /// <param name="bulk">The number of traversers represented in this traverser.</param>
-        public Traverser(dynamic obj, long bulk = 1)
+        public Traverser(dynamic? obj, long bulk = 1)
         {
             Object = obj;
             Bulk = bulk;
@@ -42,7 +42,7 @@
         /// <summary>
         ///     Gets the object of this traverser.
         /// </summary>
-        public dynamic Object { get; }
+        public dynamic? Object { get; }
 
         /// <summary>
         ///     Gets the number of traversers represented in this traverser.
@@ -50,7 +50,7 @@
         public long Bulk { get; internal set; }
 
         /// <inheritdoc />
-        public bool Equals(Traverser other)
+        public bool Equals(Traverser? other)
         {
             if (ReferenceEquals(null, other)) return false;
             if (ReferenceEquals(this, other)) return true;
@@ -58,7 +58,7 @@
         }
 
         /// <inheritdoc />
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             if (ReferenceEquals(null, obj)) return false;
             if (ReferenceEquals(this, obj)) return true;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
index 93de0b8..17adcda 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
@@ -42,7 +42,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the V step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Vertex> V(params object[] vertexIdsOrElements)
+        public static GraphTraversal<object, Vertex> V(params object?[]? vertexIdsOrElements)
         {
             return vertexIdsOrElements is { Length: 0 }
                 ? new GraphTraversal<object, Vertex>().V()
@@ -50,6 +50,16 @@
         }
 
         /// <summary>
+        ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the E step to that traversal.
+        /// </summary>
+        public static GraphTraversal<object, Edge> E(params object?[]? edgeIdsOrElements)
+        {
+            return edgeIdsOrElements is { Length: 0 }
+                ? new GraphTraversal<object, Edge>().E()
+                : new GraphTraversal<object, Edge>().E(edgeIdsOrElements);
+        }
+
+        /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the addE step to that traversal.
         /// </summary>
         public static GraphTraversal<object, Edge> AddE(string edgeLabel)
@@ -152,7 +162,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the both step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Vertex> Both(params string[] edgeLabels)
+        public static GraphTraversal<object, Vertex> Both(params string?[] edgeLabels)
         {
             return edgeLabels is { Length: 0 }
                 ? new GraphTraversal<object, Vertex>().Both()
@@ -162,7 +172,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the bothE step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Edge> BothE(params string[] edgeLabels)
+        public static GraphTraversal<object, Edge> BothE(params string?[] edgeLabels)
         {
             return edgeLabels is { Length: 0 }
                 ? new GraphTraversal<object, Edge>().BothE()
@@ -180,7 +190,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the branch step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, E2> Branch<E2>(IFunction function)
+        public static GraphTraversal<object, E2> Branch<E2>(IFunction? function)
         {
             return new GraphTraversal<object, E2>().Branch<E2>(function);            
         }
@@ -196,7 +206,7 @@
         /// <summary>
         ///     Adds the call step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public static GraphTraversal<object, E2> Call<E2>(string service)
+        public static GraphTraversal<object, E2> Call<E2>(string? service)
         {
             return new GraphTraversal<object, E2>().Call<E2>(service);
         }
@@ -204,7 +214,7 @@
         /// <summary>
         ///     Adds the call step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public static GraphTraversal<object, E2> Call<E2>(string service, IDictionary<object,object> m)
+        public static GraphTraversal<object, E2> Call<E2>(string? service, IDictionary<object,object>? m)
         {
             return new GraphTraversal<object, E2>().Call<E2>(service, m);
         }
@@ -212,7 +222,7 @@
         /// <summary>
         ///     Adds the call step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public static GraphTraversal<object, E2> Call<E2>(string service, ITraversal t)
+        public static GraphTraversal<object, E2> Call<E2>(string? service, ITraversal? t)
         {
             return new GraphTraversal<object, E2>().Call<E2>(service, t);
         }
@@ -220,7 +230,7 @@
         /// <summary>
         ///     Adds the call step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public static GraphTraversal<object, E2> Call<E2>(string service, IDictionary<object,object> m, ITraversal t)
+        public static GraphTraversal<object, E2> Call<E2>(string? service, IDictionary<object,object>? m, ITraversal? t)
         {
             return new GraphTraversal<object, E2>().Call<E2>(service, m, t);
         }
@@ -306,7 +316,7 @@
         /// </summary>
         public static GraphTraversal<object, E2> Constant<E2>(E2 a)
         {
-            return new GraphTraversal<object, E2>().Constant<E2>(a);            
+            return new GraphTraversal<object, E2>().Constant(a);            
         }
 
         /// <summary>
@@ -336,7 +346,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the dedup step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Dedup(Scope scope, params string[] dedupLabels)
+        public static GraphTraversal<object, object> Dedup(Scope scope, params string?[] dedupLabels)
         {
             return dedupLabels is { Length: 0 }
                 ? new GraphTraversal<object, object>().Dedup(scope)
@@ -346,7 +356,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the dedup step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Dedup(params string[] dedupLabels)
+        public static GraphTraversal<object, object> Dedup(params string?[] dedupLabels)
         {
             return dedupLabels is { Length: 0 }
                 ? new GraphTraversal<object, object>().Dedup()
@@ -372,7 +382,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the elementMap step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, IDictionary<object, E2>> ElementMap<E2>(params string[] propertyKeys)
+        public static GraphTraversal<object, IDictionary<object, E2>> ElementMap<E2>(params string?[] propertyKeys)
         {
             return propertyKeys is { Length: 0 }
                 ? new GraphTraversal<object, IDictionary<object, E2>>().ElementMap<E2>()
@@ -414,7 +424,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the fail step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Fail(string msg)
+        public static GraphTraversal<object, object> Fail(string? msg)
         {
             return new GraphTraversal<object, object>().Fail(msg);
         }
@@ -422,7 +432,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the filter step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Filter(IPredicate predicate)
+        public static GraphTraversal<object, object> Filter(IPredicate? predicate)
         {
             return new GraphTraversal<object, object>().Filter(predicate);            
         }
@@ -438,7 +448,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the flatMap step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, E2> FlatMap<E2>(IFunction function)
+        public static GraphTraversal<object, E2> FlatMap<E2>(IFunction? function)
         {
             return new GraphTraversal<object, E2>().FlatMap<E2>(function);            
         }
@@ -462,9 +472,9 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the fold step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, E2> Fold<E2>(E2 seed, IBiFunction foldFunction)
+        public static GraphTraversal<object, E2> Fold<E2>(E2 seed, IBiFunction? foldFunction)
         {
-            return new GraphTraversal<object, E2>().Fold<E2>(seed, foldFunction);            
+            return new GraphTraversal<object, E2>().Fold(seed, foldFunction);            
         }
 
         /// <summary>
@@ -502,7 +512,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the has step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Has(string propertyKey)
+        public static GraphTraversal<object, object> Has(string? propertyKey)
         {
             return new GraphTraversal<object, object>().Has(propertyKey);            
         }
@@ -510,7 +520,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the has step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Has(string propertyKey, object value)
+        public static GraphTraversal<object, object> Has(string? propertyKey, object? value)
         {
             return new GraphTraversal<object, object>().Has(propertyKey, value);            
         }
@@ -518,7 +528,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the has step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Has(string propertyKey, P predicate)
+        public static GraphTraversal<object, object> Has(string? propertyKey, P? predicate)
         {
             return new GraphTraversal<object, object>().Has(propertyKey, predicate);            
         }
@@ -526,7 +536,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the has step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Has(string label, string propertyKey, object value)
+        public static GraphTraversal<object, object> Has(string? label, string? propertyKey, object? value)
         {
             return new GraphTraversal<object, object>().Has(label, propertyKey, value);            
         }
@@ -534,7 +544,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the has step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Has(string label, string propertyKey, P predicate)
+        public static GraphTraversal<object, object> Has(string? label, string? propertyKey, P? predicate)
         {
             return new GraphTraversal<object, object>().Has(label, propertyKey, predicate);            
         }
@@ -542,7 +552,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the has step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Has(string propertyKey, ITraversal propertyTraversal)
+        public static GraphTraversal<object, object> Has(string? propertyKey, ITraversal propertyTraversal)
         {
             return new GraphTraversal<object, object>().Has(propertyKey, propertyTraversal);            
         }
@@ -550,7 +560,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the has step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Has(T accessor, object value)
+        public static GraphTraversal<object, object> Has(T accessor, object? value)
         {
             return new GraphTraversal<object, object>().Has(accessor, value);            
         }
@@ -558,7 +568,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the has step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Has(T accessor, P predicate)
+        public static GraphTraversal<object, object> Has(T accessor, P? predicate)
         {
             return new GraphTraversal<object, object>().Has(accessor, predicate);            
         }
@@ -574,7 +584,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the hasId step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> HasId(object id, params object[] otherIds)
+        public static GraphTraversal<object, object> HasId(object? id, params object?[]? otherIds)
         {
             return otherIds is { Length: 0 }
                 ? new GraphTraversal<object, object>().HasId(id)
@@ -584,7 +594,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the hasId step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> HasId(P predicate)
+        public static GraphTraversal<object, object> HasId(P? predicate)
         {
             return new GraphTraversal<object, object>().HasId(predicate);            
         }
@@ -592,7 +602,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the hasKey step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> HasKey(P predicate)
+        public static GraphTraversal<object, object> HasKey(P? predicate)
         {
             return new GraphTraversal<object, object>().HasKey(predicate);            
         }
@@ -600,7 +610,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the hasKey step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> HasKey(string label, params string[] otherLabels)
+        public static GraphTraversal<object, object> HasKey(string? label, params string?[]? otherLabels)
         {
             return otherLabels is { Length: 0 }
                 ? new GraphTraversal<object, object>().HasKey(label)
@@ -610,7 +620,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the hasLabel step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> HasLabel(P predicate)
+        public static GraphTraversal<object, object> HasLabel(P? predicate)
         {
             return new GraphTraversal<object, object>().HasLabel(predicate);            
         }
@@ -618,7 +628,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the hasLabel step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> HasLabel(string label, params string[] otherLabels)
+        public static GraphTraversal<object, object> HasLabel(string? label, params string?[]? otherLabels)
         {
             return otherLabels is { Length: 0 }
                 ? new GraphTraversal<object, object>().HasLabel(label)
@@ -628,7 +638,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the hasNot step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> HasNot(string propertyKey)
+        public static GraphTraversal<object, object> HasNot(string? propertyKey)
         {
             return new GraphTraversal<object, object>().HasNot(propertyKey);            
         }
@@ -636,7 +646,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the hasValue step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> HasValue(object value, params object[] values)
+        public static GraphTraversal<object, object> HasValue(object? value, params object?[]? values)
         {
             return values is { Length: 0 }
                 ? new GraphTraversal<object, object>().HasValue(value)
@@ -646,7 +656,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the hasValue step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> HasValue(P predicate)
+        public static GraphTraversal<object, object> HasValue(P? predicate)
         {
             return new GraphTraversal<object, object>().HasValue(predicate);            
         }
@@ -670,7 +680,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the in step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Vertex> In(params string[] edgeLabels)
+        public static GraphTraversal<object, Vertex> In(params string?[] edgeLabels)
         {
             return edgeLabels is { Length: 0 }
                 ? new GraphTraversal<object, Vertex>().In()
@@ -680,7 +690,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the inE step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Edge> InE(params string[] edgeLabels)
+        public static GraphTraversal<object, Edge> InE(params string?[] edgeLabels)
         {
             return edgeLabels is { Length: 0 }
                 ? new GraphTraversal<object, Edge>().InE()
@@ -706,7 +716,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the inject step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Inject(params object[] injections)
+        public static GraphTraversal<object, object> Inject(params object?[] injections)
         {
             return injections is { Length: 0 }
                 ? new GraphTraversal<object, object>().Inject()
@@ -716,7 +726,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the is step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Is(object value)
+        public static GraphTraversal<object, object> Is(object? value)
         {
             return new GraphTraversal<object, object>().Is(value);            
         }
@@ -724,7 +734,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the is step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Is(P predicate)
+        public static GraphTraversal<object, object> Is(P? predicate)
         {
             return new GraphTraversal<object, object>().Is(predicate);            
         }
@@ -780,7 +790,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the loops step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, int> Loops(string loopName)
+        public static GraphTraversal<object, int> Loops(string? loopName)
         {
             return new GraphTraversal<object, int>().Loops(loopName);            
         }
@@ -788,7 +798,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the map step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, E2> Map<E2>(IFunction function)
+        public static GraphTraversal<object, E2> Map<E2>(IFunction? function)
         {
             return new GraphTraversal<object, E2>().Map<E2>(function);            
         }
@@ -862,7 +872,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the mergeE step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Edge> MergeE (IDictionary<object,object> m)
+        public static GraphTraversal<object, Edge> MergeE (IDictionary<object,object>? m)
         {
             return new GraphTraversal<object, Edge>().MergeE(m);
         }
@@ -870,7 +880,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the mergeE step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Edge> MergeE (ITraversal t)
+        public static GraphTraversal<object, Edge> MergeE (ITraversal? t)
         {
             return new GraphTraversal<object, Edge>().MergeE(t);
         }
@@ -886,7 +896,7 @@
         /// <summary>
         ///     Adds the mergeV step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public static GraphTraversal<object, Vertex> MergeV (IDictionary<object,object> m)
+        public static GraphTraversal<object, Vertex> MergeV (IDictionary<object,object>? m)
         {
             return new GraphTraversal<object, Vertex>().MergeV(m);
         }
@@ -894,7 +904,7 @@
         /// <summary>
         ///     Adds the mergeV step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
-        public static GraphTraversal<object, Vertex> MergeV (ITraversal t)
+        public static GraphTraversal<object, Vertex> MergeV (ITraversal? t)
         {
             return new GraphTraversal<object, Vertex>().MergeV(t);
         }
@@ -968,7 +978,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the out step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Vertex> Out(params string[] edgeLabels)
+        public static GraphTraversal<object, Vertex> Out(params string?[] edgeLabels)
         {
             return edgeLabels is { Length: 0 }
                 ? new GraphTraversal<object, Vertex>().Out()
@@ -978,7 +988,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the outE step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Edge> OutE(params string[] edgeLabels)
+        public static GraphTraversal<object, Edge> OutE(params string?[] edgeLabels)
         {
             return edgeLabels is { Length: 0 }
                 ? new GraphTraversal<object, Edge>().OutE()
@@ -1004,7 +1014,8 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the project step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, IDictionary<string, E2>> Project<E2>(string projectKey, params string[] projectKeys)
+        public static GraphTraversal<object, IDictionary<string, E2>> Project<E2>(string? projectKey,
+            params string?[] projectKeys)
         {
             return projectKeys is { Length: 0 }
                 ? new GraphTraversal<object, IDictionary<string, E2>>().Project<E2>(projectKey)
@@ -1014,7 +1025,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the properties step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, E2> Properties<E2>(params string[] propertyKeys)
+        public static GraphTraversal<object, E2> Properties<E2>(params string?[] propertyKeys)
         {
             return propertyKeys is { Length: 0 }
                 ? new GraphTraversal<object, E2>().Properties<E2>()
@@ -1024,7 +1035,8 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the property step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Property(Cardinality cardinality, object key, object value, params object[] keyValues)
+        public static GraphTraversal<object, object> Property(Cardinality cardinality, object? key, object? value,
+            params object?[] keyValues)
         {
             return keyValues is { Length: 0 }
                 ? new GraphTraversal<object, object>().Property(cardinality, key, value)
@@ -1034,7 +1046,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the property step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> Property(object key, object value, params object[] keyValues)
+        public static GraphTraversal<object, object> Property(object? key, object? value, params object?[] keyValues)
         {
             return keyValues is { Length: 0 }
                 ? new GraphTraversal<object, object>().Property(key, value)
@@ -1044,7 +1056,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the propertyMap step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, IDictionary<string, E2>> PropertyMap<E2>(params string[] propertyKeys)
+        public static GraphTraversal<object, IDictionary<string, E2>> PropertyMap<E2>(params string?[] propertyKeys)
         {
             return propertyKeys is { Length: 0 }
                 ? new GraphTraversal<object, IDictionary<string, E2>>().PropertyMap<E2>()
@@ -1126,7 +1138,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the select step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, E2> Select<E2>(Pop pop, string selectKey)
+        public static GraphTraversal<object, E2> Select<E2>(Pop pop, string? selectKey)
         {
             return new GraphTraversal<object, E2>().Select<E2>(pop, selectKey);            
         }
@@ -1134,11 +1146,13 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the select step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, IDictionary<string, E2>> Select<E2>(Pop pop, string selectKey1, string selectKey2, params string[] otherSelectKeys)
+        public static GraphTraversal<object, IDictionary<string, E2>> Select<E2>(Pop pop, string? selectKey1,
+            string? selectKey2, params string?[] otherSelectKeys)
         {
             return otherSelectKeys is { Length: 0 }
                 ? new GraphTraversal<object, IDictionary<string, E2>>().Select<E2>(pop, selectKey1, selectKey2)
-                : new GraphTraversal<object, IDictionary<string, E2>>().Select<E2>(pop, selectKey1, selectKey2, otherSelectKeys);            
+                : new GraphTraversal<object, IDictionary<string, E2>>().Select<E2>(pop, selectKey1, selectKey2,
+                    otherSelectKeys);
         }
 
         /// <summary>
@@ -1152,7 +1166,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the select step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, E2> Select<E2>(string selectKey)
+        public static GraphTraversal<object, E2> Select<E2>(string? selectKey)
         {
             return new GraphTraversal<object, E2>().Select<E2>(selectKey);            
         }
@@ -1160,11 +1174,13 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the select step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, IDictionary<string, E2>> Select<E2>(string selectKey1, string selectKey2, params string[] otherSelectKeys)
+        public static GraphTraversal<object, IDictionary<string, E2>> Select<E2>(string? selectKey1, string? selectKey2,
+            params string?[] otherSelectKeys)
         {
             return otherSelectKeys is { Length: 0 }
                 ? new GraphTraversal<object, IDictionary<string, E2>>().Select<E2>(selectKey1, selectKey2)
-                : new GraphTraversal<object, IDictionary<string, E2>>().Select<E2>(selectKey1, selectKey2, otherSelectKeys);            
+                : new GraphTraversal<object, IDictionary<string, E2>>().Select<E2>(selectKey1, selectKey2,
+                    otherSelectKeys);
         }
 
         /// <summary>
@@ -1178,7 +1194,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the sideEffect step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, object> SideEffect(IConsumer consumer)
+        public static GraphTraversal<object, object> SideEffect(IConsumer? consumer)
         {
             return new GraphTraversal<object, object>().SideEffect(consumer);            
         }
@@ -1298,7 +1314,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the to step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Vertex> To(Direction direction, params string[] edgeLabels)
+        public static GraphTraversal<object, Vertex> To(Direction? direction, params string?[] edgeLabels)
         {
             return edgeLabels is { Length: 0 }
                 ? new GraphTraversal<object, Vertex>().To(direction)
@@ -1308,7 +1324,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the toE step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Edge> ToE(Direction direction, params string[] edgeLabels)
+        public static GraphTraversal<object, Edge> ToE(Direction? direction, params string?[] edgeLabels)
         {
             return edgeLabels is { Length: 0 }
                 ? new GraphTraversal<object, Edge>().ToE(direction)
@@ -1318,7 +1334,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the toV step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, Vertex> ToV(Direction direction)
+        public static GraphTraversal<object, Vertex> ToV(Direction? direction)
         {
             return new GraphTraversal<object, Vertex>().ToV(direction);            
         }
@@ -1384,7 +1400,8 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the valueMap step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, IDictionary<TKey, TValue>> ValueMap<TKey, TValue>(params string[] propertyKeys)
+        public static GraphTraversal<object, IDictionary<TKey, TValue>> ValueMap<TKey, TValue>(
+            params string?[] propertyKeys)
         {
             return propertyKeys is { Length: 0 }
                 ? new GraphTraversal<object, IDictionary<TKey, TValue>>().ValueMap<TKey, TValue>()
@@ -1394,7 +1411,8 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the valueMap step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, IDictionary<TKey, TValue>> ValueMap<TKey, TValue>(bool includeTokens, params string[] propertyKeys)
+        public static GraphTraversal<object, IDictionary<TKey, TValue>> ValueMap<TKey, TValue>(bool includeTokens,
+            params string?[] propertyKeys)
         {
             return propertyKeys is { Length: 0 }
                 ? new GraphTraversal<object, IDictionary<TKey, TValue>>().ValueMap<TKey, TValue>(includeTokens)
@@ -1404,7 +1422,7 @@
         /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the values step to that traversal.
         /// </summary>
-        public static GraphTraversal<object, E2> Values<E2>(params string[] propertyKeys)
+        public static GraphTraversal<object, E2> Values<E2>(params string?[] propertyKeys)
         {
             return propertyKeys is { Length: 0 }
                 ? new GraphTraversal<object, E2>().Values<E2>()
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Utils.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Utils.cs
index 81aa3e0..f7ca22d 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Utils.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Utils.cs
@@ -34,8 +34,11 @@
     /// </summary>
     internal static class Utils
     {
+        /// <summary>
+        /// The user agent which is sent with connection requests if enabled.
+        /// </summary>
         public static string UserAgent => _userAgent ??= GenerateUserAgent();
-        private static string _userAgent;
+        private static string? _userAgent;
         
         /// <summary>
         /// Waits the completion of the provided Task.
@@ -49,7 +52,7 @@
             }
             catch (AggregateException ex)
             {
-                if (ex.InnerExceptions.Count == 1)
+                if (ex.InnerException != null)
                 {
                     ExceptionDispatchInfo.Capture(ex.InnerException).Throw();   
                 }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Properties/AssemblyInfo.cs b/gremlin-dotnet/src/Gremlin.Net/Properties/AssemblyInfo.cs
index 4351b0e..e6c1a7e 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Properties/AssemblyInfo.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Properties/AssemblyInfo.cs
@@ -24,4 +24,5 @@
 using System.Runtime.CompilerServices;
 
 [assembly: InternalsVisibleTo("Gremlin.Net.UnitTest, PublicKey=00240000048000009400000006020000002400005253413100040000010001009bbf7a5b9966d9207d8abb9d3d3e98f5e387b292742cfb791dc657357221c3ac9b38ab6dab89630dc8edb3cde84a107f493d192116a934afa463355eefd58b82fd08dc2616ee6074a74bf5845652864746e285bd04e2e1a87921e8e2c383d1b302e7bee1fd7cdab5fe2bbed8c6677624d63433548d43a873ab5650ed96fb0687")]
+[assembly: InternalsVisibleTo("Gremlin.Net.IntegrationTest, PublicKey=00240000048000009400000006020000002400005253413100040000010001009bbf7a5b9966d9207d8abb9d3d3e98f5e387b292742cfb791dc657357221c3ac9b38ab6dab89630dc8edb3cde84a107f493d192116a934afa463355eefd58b82fd08dc2616ee6074a74bf5845652864746e285bd04e2e1a87921e8e2c383d1b302e7bee1fd7cdab5fe2bbed8c6677624d63433548d43a873ab5650ed96fb0687")]
 [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/Edge.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/Edge.cs
index fddbd69..1989004 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/Edge.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/Edge.cs
@@ -21,6 +21,8 @@
 
 #endregion
 
+using System.Linq;
+
 namespace Gremlin.Net.Structure
 {
     /// <summary>
@@ -35,22 +37,32 @@
         /// <param name="outV">The outgoing/tail vertex of the edge.</param>
         /// <param name="label">The label of the edge.</param>
         /// <param name="inV">The incoming/head vertex of the edge.</param>
-        public Edge(object id, Vertex outV, string label, Vertex inV)
-            : base(id, label)
+        /// <param name="properties">Optional properties of the edge.</param>
+        public Edge(object? id, Vertex outV, string label, Vertex inV, dynamic[]? properties = null)
+            : base(id, label, properties)
         {
             OutV = outV;
             InV = inV;
         }
 
         /// <summary>
-        ///     Gets or sets the incoming/head vertex of this edge.
+        ///     Gets the incoming/head vertex of this edge.
         /// </summary>
-        public Vertex InV { get; set; }
+        public Vertex InV { get; }
 
         /// <summary>
-        ///     Gets or sets the outgoing/tail vertex of this edge.
+        ///     Gets the outgoing/tail vertex of this edge.
         /// </summary>
-        public Vertex OutV { get; set; }
+        public Vertex OutV { get; }
+
+        /// <summary>
+        /// Get property by key
+        /// </summary>
+        /// <returns>property or null when not found</returns>
+        public Property? Property(string key)
+        {
+            return Properties?.Cast<Property>().FirstOrDefault(p => p.Key == key);
+        }
 
         /// <inheritdoc />
         public override string ToString()
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/Element.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/Element.cs
index f4fc847..32935bd 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/Element.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/Element.cs
@@ -22,6 +22,7 @@
 #endregion
 
 using System;
+using System.Collections.Generic;
 
 namespace Gremlin.Net.Structure
 {
@@ -35,24 +36,31 @@
         /// </summary>
         /// <param name="id">The id of the element.</param>
         /// <param name="label">The label of the element.</param>
-        protected Element(object id, string label)
+        /// <param name="properties">Optional properties of the element.</param>
+        protected Element(object? id, string label, dynamic[]? properties = null)
         {
             Id = id;
             Label = label;
+            Properties = properties;
         }
 
         /// <summary>
         ///     Gets the id of this <see cref="Element" />.
         /// </summary>
-        public object Id { get; }
+        public object? Id { get; }
 
         /// <summary>
         ///     Gets the label of this <see cref="Element" />.
         /// </summary>
         public string Label { get; }
 
+        /// <summary>
+        ///     Gets the properties of this <see cref="Element" />.
+        /// </summary>
+        public dynamic[]? Properties { get; }
+
         /// <inheritdoc />
-        public bool Equals(Element other)
+        public bool Equals(Element? other)
         {
             if (ReferenceEquals(null, other)) return false;
             if (ReferenceEquals(this, other)) return true;
@@ -60,7 +68,7 @@
         }
 
         /// <inheritdoc />
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             if (ReferenceEquals(null, obj)) return false;
             if (ReferenceEquals(this, obj)) return true;
@@ -71,7 +79,7 @@
         /// <inheritdoc />
         public override int GetHashCode()
         {
-            return Id.GetHashCode();
+            return Id != null ? Id.GetHashCode() : 0;
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/DataType.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/DataType.cs
index ee33cee..b5c5e0c 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/DataType.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/DataType.cs
@@ -108,7 +108,7 @@
         }
 
         /// <inheritdoc />
-        public bool Equals(DataType other)
+        public bool Equals(DataType? other)
         {
             if (ReferenceEquals(null, other)) return false;
             if (ReferenceEquals(this, other)) return true;
@@ -116,7 +116,7 @@
         }
 
         /// <inheritdoc />
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             if (ReferenceEquals(null, obj)) return false;
             if (ReferenceEquals(this, obj)) return true;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryMessageSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryMessageSerializer.cs
index 0ea1435..eeee25d 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryMessageSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryMessageSerializer.cs
@@ -49,7 +49,7 @@
         /// Initializes a new instance of the <see cref="GraphBinaryMessageSerializer" /> class.
         /// </summary>
         /// <param name="registry">The <see cref="TypeSerializerRegistry"/> to use for serialization.</param>
-        public GraphBinaryMessageSerializer(TypeSerializerRegistry registry = null)
+        public GraphBinaryMessageSerializer(TypeSerializerRegistry? registry = null)
         {
             _reader = new GraphBinaryReader(registry);
             _writer = new GraphBinaryWriter(registry);
@@ -81,7 +81,7 @@
         }
 
         /// <inheritdoc />
-        public async Task<ResponseMessage<List<object>>> DeserializeMessageAsync(byte[] message,
+        public async Task<ResponseMessage<List<object>>?> DeserializeMessageAsync(byte[] message,
             CancellationToken cancellationToken = default)
         {
             using var stream = new MemoryStream(message);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryReader.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryReader.cs
index 297bb41..6b11360 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryReader.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryReader.cs
@@ -38,7 +38,7 @@
         /// Initializes a new instance of the <see cref="GraphBinaryReader" /> class.
         /// </summary>
         /// <param name="registry">The <see cref="TypeSerializerRegistry"/> to use for deserialization.</param>
-        public GraphBinaryReader(TypeSerializerRegistry registry = null)
+        public GraphBinaryReader(TypeSerializerRegistry? registry = null)
         {
             _registry = registry ?? TypeSerializerRegistry.Instance;
         }
@@ -47,15 +47,29 @@
         /// Reads only the value for a specific type <typeparamref name="T"/>.
         /// </summary>
         /// <param name="stream">The GraphBinary data to parse.</param>
-        /// <param name="nullable">Whether or not the value can be null.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <typeparam name="T">The type of the object to read.</typeparam>
         /// <returns>The read value.</returns>
-        public async Task<object> ReadValueAsync<T>(Stream stream, bool nullable,
+        public async Task<object?> ReadNullableValueAsync<T>(Stream stream,
             CancellationToken cancellationToken = default)
         {
             var typedSerializer = _registry.GetSerializerFor(typeof(T));
-            return await typedSerializer.ReadValueAsync(stream, this, nullable, cancellationToken)
+            return await typedSerializer.ReadNullableValueAsync(stream, this, cancellationToken)
+                .ConfigureAwait(false);
+        }
+        
+        /// <summary>
+        /// Reads only the value for a specific type <typeparamref name="T"/>.
+        /// </summary>
+        /// <param name="stream">The GraphBinary data to parse.</param>
+        /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
+        /// <typeparam name="T">The type of the object to read.</typeparam>
+        /// <returns>The read value.</returns>
+        public async Task<object> ReadNonNullableValueAsync<T>(Stream stream,
+            CancellationToken cancellationToken = default)
+        {
+            var typedSerializer = _registry.GetSerializerFor(typeof(T));
+            return await typedSerializer.ReadNonNullableValueAsync(stream, this, cancellationToken)
                 .ConfigureAwait(false);
         }
 
@@ -65,14 +79,14 @@
         /// <param name="stream">The GraphBinary data to parse.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <returns>The read value.</returns>
-        public async Task<object> ReadAsync(Stream stream, CancellationToken cancellationToken = default)
+        public async Task<object?> ReadAsync(Stream stream, CancellationToken cancellationToken = default)
         {
             var type = DataType.FromTypeCode(await stream.ReadByteAsync(cancellationToken).ConfigureAwait(false));
 
             if (type == DataType.UnspecifiedNull)
             {
                 await stream.ReadByteAsync(cancellationToken).ConfigureAwait(false); // read value byte to advance the index
-                return default; // should be null (TODO?)
+                return null;
             }
 
             ITypeSerializer typeSerializer;
@@ -82,8 +96,8 @@
             }
             else
             {
-                var customTypeName =
-                    (string)await ReadValueAsync<string>(stream, false, cancellationToken).ConfigureAwait(false);
+                var customTypeName = (string)await ReadNonNullableValueAsync<string>(stream, cancellationToken)
+                    .ConfigureAwait(false);
                 typeSerializer = _registry.GetSerializerForCustomType(customTypeName);
             }
             
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryWriter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryWriter.cs
index 132707c..876611f 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryWriter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/GraphBinaryWriter.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System;
 using System.IO;
 using System.Threading;
 using System.Threading.Tasks;
@@ -50,36 +51,46 @@
         /// Initializes a new instance of the <see cref="GraphBinaryWriter" /> class.
         /// </summary>
         /// <param name="registry">The <see cref="TypeSerializerRegistry"/> to use for serialization.</param>
-        public GraphBinaryWriter(TypeSerializerRegistry registry = null)
+        public GraphBinaryWriter(TypeSerializerRegistry? registry = null)
         {
             _registry = registry ?? TypeSerializerRegistry.Instance;
         }
 
         /// <summary>
-        /// Writes a value without including type information.
+        /// Writes a nullable value without including type information.
         /// </summary>
         /// <param name="value">The value to write.</param>
         /// <param name="stream">The stream to write to.</param>
-        /// <param name="nullable">Whether or not the value can be null.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <returns>A task that represents the asynchronous write operation.</returns>
-        public async Task WriteValueAsync(object value, Stream stream, bool nullable,
+        public async Task WriteNullableValueAsync(object? value, Stream stream,
             CancellationToken cancellationToken = default)
         {
             if (value == null)
             {
-                if (!nullable)
-                {
-                    throw new IOException("Unexpected null value when nullable is false");
-                }
-
                 await WriteValueFlagNullAsync(stream, cancellationToken).ConfigureAwait(false);
                 return;
             }
             
             var valueType = value.GetType();
             var serializer = _registry.GetSerializerFor(valueType);
-            await serializer.WriteValueAsync(value, stream, this, nullable, cancellationToken).ConfigureAwait(false);
+            await serializer.WriteNullableValueAsync(value, stream, this, cancellationToken).ConfigureAwait(false);
+        }
+        
+        /// <summary>
+        /// Writes a non-nullable value without including type information.
+        /// </summary>
+        /// <param name="value">The value to write.</param>
+        /// <param name="stream">The stream to write to.</param>
+        /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
+        /// <returns>A task that represents the asynchronous write operation.</returns>
+        public async Task WriteNonNullableValueAsync(object value, Stream stream,
+            CancellationToken cancellationToken = default)
+        {
+            if (value == null) throw new IOException($"{nameof(value)} cannot be null");
+            var valueType = value.GetType();
+            var serializer = _registry.GetSerializerFor(valueType);
+            await serializer.WriteNonNullableValueAsync(value, stream, this, cancellationToken).ConfigureAwait(false);
         }
 
         /// <summary>
@@ -89,7 +100,7 @@
         /// <param name="stream">The stream to write to.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <returns>A task that represents the asynchronous write operation.</returns>
-        public async Task WriteAsync(object value, Stream stream, CancellationToken cancellationToken = default)
+        public async Task WriteAsync(object? value, Stream stream, CancellationToken cancellationToken = default)
         {
             if (value == null)
             {
@@ -103,7 +114,7 @@
             if (serializer is CustomTypeSerializer customTypeSerializer)
             {
                 await stream.WriteAsync(CustomTypeCodeBytes, cancellationToken).ConfigureAwait(false);
-                await WriteValueAsync(customTypeSerializer.TypeName, stream, false, cancellationToken)
+                await WriteNonNullableValueAsync(customTypeSerializer.TypeName, stream, cancellationToken)
                     .ConfigureAwait(false);
                 await customTypeSerializer.WriteAsync(value, stream, this, cancellationToken).ConfigureAwait(false);
                 return;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/ITypeSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/ITypeSerializer.cs
index 6bbe52a..40605dd 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/ITypeSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/ITypeSerializer.cs
@@ -49,15 +49,25 @@
             CancellationToken cancellationToken = default);
 
         /// <summary>
-        /// Writes the value to a stream, composed by the value flag and the sequence of bytes.
+        /// Writes the nullable value to a stream, composed by the value flag and the sequence of bytes.
         /// </summary>
         /// <param name="value">The value to write.</param>
         /// <param name="stream">The stream to write to.</param>
         /// <param name="writer">A <see cref="GraphBinaryWriter"/> that can be used to write nested values.</param>
-        /// <param name="nullable">Whether or not the value can be null.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <returns>A task that represents the asynchronous write operation.</returns>
-        Task WriteValueAsync(object value, Stream stream, GraphBinaryWriter writer, bool nullable,
+        Task WriteNullableValueAsync(object value, Stream stream, GraphBinaryWriter writer,
+            CancellationToken cancellationToken = default);
+        
+        /// <summary>
+        /// Writes the non-nullable value to a stream, composed by the value flag and the sequence of bytes.
+        /// </summary>
+        /// <param name="value">The value to write.</param>
+        /// <param name="stream">The stream to write to.</param>
+        /// <param name="writer">A <see cref="GraphBinaryWriter"/> that can be used to write nested values.</param>
+        /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
+        /// <returns>A task that represents the asynchronous write operation.</returns>
+        Task WriteNonNullableValueAsync(object value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default);
 
         /// <summary>
@@ -67,17 +77,26 @@
         /// <param name="reader">A <see cref="GraphBinaryReader"/> that can be used to read nested values.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <returns>The read value.</returns>
-        Task<object> ReadAsync(Stream stream, GraphBinaryReader reader, CancellationToken cancellationToken = default);
+        Task<object?> ReadAsync(Stream stream, GraphBinaryReader reader, CancellationToken cancellationToken = default);
 
         /// <summary>
         /// Reads the value from the stream (not the type information).
         /// </summary>
         /// <param name="stream">The GraphBinary data to parse.</param>
         /// <param name="reader">A <see cref="GraphBinaryReader"/> that can be used to read nested values.</param>
-        /// <param name="nullable">Whether or not the value can be null.</param>
         /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
         /// <returns>The read value.</returns>
-        Task<object> ReadValueAsync(Stream stream, GraphBinaryReader reader, bool nullable,
+        Task<object?> ReadNullableValueAsync(Stream stream, GraphBinaryReader reader,
+            CancellationToken cancellationToken = default);
+
+        /// <summary>
+        /// Reads the value from the stream (not the type information).
+        /// </summary>
+        /// <param name="stream">The GraphBinary data to parse.</param>
+        /// <param name="reader">A <see cref="GraphBinaryReader"/> that can be used to read nested values.</param>
+        /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param>
+        /// <returns>The read value.</returns>
+        Task<object> ReadNonNullableValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default);
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/RequestMessageSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/RequestMessageSerializer.cs
index e4bf380..8b489e1 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/RequestMessageSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/RequestMessageSerializer.cs
@@ -45,13 +45,13 @@
             CancellationToken cancellationToken = default)
         {
             await stream.WriteByteAsync(GraphBinaryWriter.VersionByte, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(requestMessage.RequestId, stream, false, cancellationToken)
+            await writer.WriteNonNullableValueAsync(requestMessage.RequestId, stream, cancellationToken)
                 .ConfigureAwait(false);
-            await writer.WriteValueAsync(requestMessage.Operation, stream, false, cancellationToken)
+            await writer.WriteNonNullableValueAsync(requestMessage.Operation, stream, cancellationToken)
                 .ConfigureAwait(false);
-            await writer.WriteValueAsync(requestMessage.Processor, stream, false, cancellationToken)
+            await writer.WriteNonNullableValueAsync(requestMessage.Processor, stream, cancellationToken)
                 .ConfigureAwait(false);
-            await writer.WriteValueAsync(requestMessage.Arguments, stream, false, cancellationToken)
+            await writer.WriteNonNullableValueAsync(requestMessage.Arguments, stream, cancellationToken)
                 .ConfigureAwait(false);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/ResponseMessageSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/ResponseMessageSerializer.cs
index 3a0fa6a..e31c7a2 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/ResponseMessageSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/ResponseMessageSerializer.cs
@@ -55,34 +55,23 @@
             }
 
             var requestId =
-                (Guid?)await reader.ReadValueAsync<Guid>(stream, true, cancellationToken).ConfigureAwait(false);
-            var code = (ResponseStatusCode)await reader.ReadValueAsync<int>(stream, false, cancellationToken)
+                (Guid?)await reader.ReadNullableValueAsync<Guid>(stream, cancellationToken).ConfigureAwait(false);
+            var code = (ResponseStatusCode)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken)
                 .ConfigureAwait(false);
-            var message = (string)await reader.ReadValueAsync<string>(stream, true, cancellationToken)
+            var message = (string?)await reader.ReadNullableValueAsync<string>(stream, cancellationToken)
                 .ConfigureAwait(false);
             var dictObj = await reader
-                .ReadValueAsync<Dictionary<string, object>>(stream, false, cancellationToken).ConfigureAwait(false);
+                .ReadNonNullableValueAsync<Dictionary<string, object>>(stream, cancellationToken).ConfigureAwait(false);
             var attributes = (Dictionary<string, object>)dictObj;
 
-            var status = new ResponseStatus
-            {
-                Code = code,
-                Message = message,
-                Attributes = attributes
-            };
-            var result = new ResponseResult<List<object>>
-            {
-                Meta = (Dictionary<string, object>)await reader
-                    .ReadValueAsync<Dictionary<string, object>>(stream, false, cancellationToken).ConfigureAwait(false),
-                Data = (List<object>)await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false)
-            };
+            var status = new ResponseStatus(code, attributes, message);
 
-            return new ResponseMessage<List<object>>
-            {
-                RequestId = requestId,
-                Status = status,
-                Result = result
-            };
+            var meta = (Dictionary<string, object>)await reader
+                .ReadNonNullableValueAsync<Dictionary<string, object>>(stream, cancellationToken).ConfigureAwait(false);
+            var data = (List<object>?)await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+            var result = new ResponseResult<List<object>>(data, meta);
+
+            return new ResponseMessage<List<object>>(requestId, status, result);
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/TypeSerializerRegistry.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/TypeSerializerRegistry.cs
index eca99cf..58cca37 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/TypeSerializerRegistry.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/TypeSerializerRegistry.cs
@@ -23,6 +23,8 @@
 
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
 using System.Linq;
 using System.Numerics;
 using Gremlin.Net.Process.Traversal;
@@ -95,7 +97,7 @@
                 {DataType.Float, SingleTypeSerializers.FloatSerializer},
                 {DataType.List, new ListSerializer<object>()},
                 {DataType.Map, new MapSerializer<object, object>()},
-                {DataType.Set, new SetSerializer<HashSet<object>, object>()},
+                {DataType.Set, new SetSerializer<HashSet<object?>, object>()},
                 {DataType.Uuid, new UuidSerializer()},
                 {DataType.Edge, new EdgeSerializer()},
                 {DataType.Path, new PathSerializer()},
@@ -169,8 +171,10 @@
             if (IsDictionaryType(valueType, out var dictKeyType, out var dictValueType))
             {
                 var serializerType = typeof(MapSerializer<,>).MakeGenericType(dictKeyType, dictValueType);
-                var serializer = (ITypeSerializer) Activator.CreateInstance(serializerType);
-                _serializerByType[valueType] = serializer;
+                var serializer = (ITypeSerializer?) Activator.CreateInstance(serializerType);
+                _serializerByType[valueType] = serializer ??
+                                               throw new IOException(
+                                                   $"Cannot create a serializer for the dictionary type {valueType}.");
                 return serializer;
             }
 
@@ -178,17 +182,21 @@
             {
                 var memberType = valueType.GetGenericArguments()[0];
                 var serializerType = typeof(SetSerializer<,>).MakeGenericType(valueType, memberType);
-                var serializer = (ITypeSerializer) Activator.CreateInstance(serializerType);
-                _serializerByType[valueType] = serializer;
+                var serializer = (ITypeSerializer?) Activator.CreateInstance(serializerType);
+                _serializerByType[valueType] = serializer ??
+                                               throw new IOException(
+                                                   $"Cannot create a serializer for the set type {valueType}.");
                 return serializer;
             }
 
             if (valueType.IsArray)
             {
                 var memberType = valueType.GetElementType();
-                var serializerType = typeof(ArraySerializer<>).MakeGenericType(memberType);
-                var serializer = (ITypeSerializer) Activator.CreateInstance(serializerType);
-                _serializerByType[valueType] = serializer;
+                var serializerType = typeof(ArraySerializer<>).MakeGenericType(memberType!);
+                var serializer = (ITypeSerializer?) Activator.CreateInstance(serializerType);
+                _serializerByType[valueType] = serializer ??
+                                               throw new IOException(
+                                                   $"Cannot create a serializer for the array type {valueType}.");
                 return serializer;
             }
 
@@ -196,8 +204,10 @@
             {
                 var memberType = valueType.GetGenericArguments()[0];
                 var serializerType = typeof(ListSerializer<>).MakeGenericType(memberType);
-                var serializer = (ITypeSerializer) Activator.CreateInstance(serializerType);
-                _serializerByType[valueType] = serializer;
+                var serializer = (ITypeSerializer?) Activator.CreateInstance(serializerType);
+                _serializerByType[valueType] = serializer ??
+                                               throw new IOException(
+                                                   $"Cannot create a serializer for the list type {valueType}.");
                 return serializer;
             }
 
@@ -214,7 +224,8 @@
             throw new InvalidOperationException($"No serializer found for type '{valueType}'.");
         }
 
-        private static bool IsDictionaryType(Type type, out Type keyType, out Type valueType)
+        private static bool IsDictionaryType(Type type, [NotNullWhen(returnValue: true)] out Type? keyType,
+            [NotNullWhen(returnValue: true)] out Type? valueType)
         {
             var maybeInterfaceType = type
                 .GetInterfaces()
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ArraySerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ArraySerializer.cs
index 4bd85f8..01ef44b 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ArraySerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ArraySerializer.cs
@@ -45,7 +45,7 @@
         protected override async Task WriteValueAsync(TMember[] value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Length, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Length, stream, cancellationToken).ConfigureAwait(false);
             
             foreach (var item in value)
             {
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BigDecimalSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BigDecimalSerializer.cs
index 8a3cdc6..f7fd205 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BigDecimalSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BigDecimalSerializer.cs
@@ -46,8 +46,8 @@
             CancellationToken cancellationToken = default)
         {
             var (unscaledValue, scale) = GetUnscaledValueAndScale(value);
-            await writer.WriteValueAsync(scale, stream, false, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(unscaledValue, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(scale, stream, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(unscaledValue, stream, cancellationToken).ConfigureAwait(false);
         }
         
         private static (BigInteger, int) GetUnscaledValueAndScale(decimal input)
@@ -79,8 +79,9 @@
         protected override async Task<decimal> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var scale = (int)await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
-            var unscaled = (BigInteger)await reader.ReadValueAsync<BigInteger>(stream, false, cancellationToken)
+            var scale = (int)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken)
+                .ConfigureAwait(false);
+            var unscaled = (BigInteger)await reader.ReadNonNullableValueAsync<BigInteger>(stream, cancellationToken)
                 .ConfigureAwait(false);
 
             return ConvertScaleAndUnscaledValue(scale, unscaled);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BigIntegerSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BigIntegerSerializer.cs
index efb67c5..08a2953 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BigIntegerSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BigIntegerSerializer.cs
@@ -46,7 +46,7 @@
             CancellationToken cancellationToken = default)
         {
             var bytes = value.ToByteArray().Reverse().ToArray();
-            await writer.WriteValueAsync(bytes.Length, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(bytes.Length, stream, cancellationToken).ConfigureAwait(false);
             await stream.WriteAsync(bytes, cancellationToken).ConfigureAwait(false);
         }
 
@@ -54,7 +54,7 @@
         protected override async Task<BigInteger> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var length = (int)await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
+            var length = (int)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
             var bytes = await stream.ReadAsync(length, cancellationToken).ConfigureAwait(false);
             return new BigInteger(bytes.Reverse().ToArray());
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BindingSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BindingSerializer.cs
index d7ed283..87b884e 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BindingSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BindingSerializer.cs
@@ -44,7 +44,7 @@
         protected override async Task WriteValueAsync(Binding value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Key, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Key, stream, cancellationToken).ConfigureAwait(false);
             await writer.WriteAsync(value.Value, stream, cancellationToken).ConfigureAwait(false);
         }
 
@@ -52,7 +52,7 @@
         protected override async Task<Binding> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var key = (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken)
+            var key = (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken)
                 .ConfigureAwait(false);
             var value = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
             return new Binding(key, value);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BulkSetSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BulkSetSerializer.cs
index d1471eb..6bf95cf 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BulkSetSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/BulkSetSerializer.cs
@@ -56,13 +56,13 @@
         protected override async Task<TList> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var length = (int)await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
+            var length = (int)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
 
             var result = new TList();
             for (var i = 0; i < length; i++)
             {
                 var value = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
-                var bulk = (long)await reader.ReadValueAsync<long>(stream, false, cancellationToken)
+                var bulk = (long)await reader.ReadNonNullableValueAsync<long>(stream, cancellationToken)
                     .ConfigureAwait(false);
                 for (var j = 0; j < bulk; j++)
                 {
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ByteBufferSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ByteBufferSerializer.cs
index e75550f..ca658f1 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ByteBufferSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ByteBufferSerializer.cs
@@ -44,7 +44,7 @@
         protected override async Task WriteValueAsync(byte[] value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Length, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Length, stream, cancellationToken).ConfigureAwait(false);
             await stream.WriteAsync(value, 0, value.Length, cancellationToken).ConfigureAwait(false);
         }
 
@@ -52,7 +52,7 @@
         protected override async Task<byte[]> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var length = (int)await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
+            var length = (int)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
             var buffer = new byte[length];
             await stream.ReadAsync(buffer, 0, length, cancellationToken).ConfigureAwait(false);
             return buffer;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ByteCodeSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ByteCodeSerializer.cs
index e41146c..3f043d1 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ByteCodeSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ByteCodeSerializer.cs
@@ -54,21 +54,21 @@
         private static async Task WriteInstructionsAsync(IReadOnlyCollection<Instruction> instructions, Stream stream,
             GraphBinaryWriter writer, CancellationToken cancellationToken)
         {
-            await writer.WriteValueAsync(instructions.Count, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(instructions.Count, stream, cancellationToken).ConfigureAwait(false);
 
             foreach (var instruction in instructions)
             {
-                await writer.WriteValueAsync(instruction.OperatorName, stream, false, cancellationToken)
+                await writer.WriteNonNullableValueAsync(instruction.OperatorName, stream, cancellationToken)
                     .ConfigureAwait(false);
                 await WriteArgumentsAsync(instruction.Arguments, stream, writer, cancellationToken)
                     .ConfigureAwait(false);
             }
         }
 
-        private static async Task WriteArgumentsAsync(object[] arguments, Stream stream, GraphBinaryWriter writer,
+        private static async Task WriteArgumentsAsync(object?[] arguments, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken)
         {
-            await writer.WriteValueAsync(arguments.Length, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(arguments.Length, stream, cancellationToken).ConfigureAwait(false);
 
             foreach (var value in arguments)
             {
@@ -82,11 +82,11 @@
         {
             var result = new Bytecode();
 
-            var stepsLength = (int) await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
+            var stepsLength = (int) await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
             for (var i = 0; i < stepsLength; i++)
             {
                 result.AddStep(
-                    (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken).ConfigureAwait(false),
+                    (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken).ConfigureAwait(false),
                     await ReadArgumentsAsync(stream, reader, cancellationToken).ConfigureAwait(false));
             }
             
@@ -94,19 +94,19 @@
             for (var i = 0; i < sourcesLength; i++)
             {
                 result.AddSource(
-                    (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken).ConfigureAwait(false),
+                    (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken).ConfigureAwait(false),
                     await ReadArgumentsAsync(stream, reader, cancellationToken).ConfigureAwait(false));
             }
             
             return result;
         }
 
-        private static async Task<object[]> ReadArgumentsAsync(Stream stream, GraphBinaryReader reader,
+        private static async Task<object?[]> ReadArgumentsAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken)
         {
             var valuesLength =
-                (int)await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
-            var values = new object[valuesLength];
+                (int)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
+            var values = new object?[valuesLength];
             for (var i = 0; i < valuesLength; i++)
             {
                 values[i] = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ClassSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ClassSerializer.cs
index 55b932f..8dd1763 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ClassSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ClassSerializer.cs
@@ -45,7 +45,7 @@
         protected override async Task WriteValueAsync(GremlinType value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Fqcn, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Fqcn, stream, cancellationToken).ConfigureAwait(false);
         }
 
         
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/CustomTypeSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/CustomTypeSerializer.cs
index 2721c05..8b558ed 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/CustomTypeSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/CustomTypeSerializer.cs
@@ -45,15 +45,23 @@
             CancellationToken cancellationToken = default);
 
         /// <inheritdoc />
-        public abstract Task WriteValueAsync(object value, Stream stream, GraphBinaryWriter writer, bool nullable,
+        public abstract Task WriteNullableValueAsync(object value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default);
 
         /// <inheritdoc />
-        public abstract Task<object> ReadAsync(Stream stream, GraphBinaryReader reader,
+        public abstract Task WriteNonNullableValueAsync(object value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default);
 
         /// <inheritdoc />
-        public abstract Task<object> ReadValueAsync(Stream stream, GraphBinaryReader reader, bool nullable,
+        public abstract Task<object?> ReadAsync(Stream stream, GraphBinaryReader reader,
+            CancellationToken cancellationToken = default);
+
+        /// <inheritdoc />
+        public abstract Task<object?> ReadNullableValueAsync(Stream stream, GraphBinaryReader reader,
+            CancellationToken cancellationToken = default);
+
+        /// <inheritdoc />
+        public abstract Task<object> ReadNonNullableValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default);
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EdgeSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EdgeSerializer.cs
index eade891..13de71b 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EdgeSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EdgeSerializer.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System.Collections.Generic;
 using System.IO;
 using System.Threading;
 using System.Threading.Tasks;
@@ -44,16 +45,16 @@
             CancellationToken cancellationToken = default)
         {
             await writer.WriteAsync(value.Id, stream, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(value.Label, stream, false, cancellationToken).ConfigureAwait(false);
-            
+            await writer.WriteNonNullableValueAsync(value.Label, stream, cancellationToken).ConfigureAwait(false);
+
             await writer.WriteAsync(value.InV.Id, stream, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(value.InV.Label, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.InV.Label, stream, cancellationToken).ConfigureAwait(false);
             await writer.WriteAsync(value.OutV.Id, stream, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(value.OutV.Label, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.OutV.Label, stream, cancellationToken).ConfigureAwait(false);
 
             // Placeholder for the parent vertex
             await writer.WriteAsync(null, stream, cancellationToken).ConfigureAwait(false);
-            
+
             // placeholder for the properties
             await writer.WriteAsync(null, stream, cancellationToken).ConfigureAwait(false);
         }
@@ -63,21 +64,21 @@
             CancellationToken cancellationToken = default)
         {
             var id = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
-            var label = (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken)
+            var label = (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken)
                 .ConfigureAwait(false);
 
             var inV = new Vertex(await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false),
-                (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken).ConfigureAwait(false));
+                (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken).ConfigureAwait(false));
             var outV = new Vertex(await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false),
-                (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken).ConfigureAwait(false));
-            
+                (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken).ConfigureAwait(false));
+
             // discard possible parent vertex
             await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
 
-            // discard possible properties
-            await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+            var properties = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+            var propertiesAsArray = (properties as List<object>)?.ToArray();
 
-            return new Edge(id, outV, label, inV);
+            return new Edge(id, outV, label, inV, propertiesAsArray);
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EnumSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EnumSerializer.cs
index 1d94235..69e902d 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EnumSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/EnumSerializer.cs
@@ -127,7 +127,10 @@
         protected override async Task<TEnum> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var enumValue = (string) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+            // This should probably be `reader.ReadNonNullableValueAsync<string>(stream, cancellationToken)` instead,
+            // but it's the same in other GLVs and changing this would be a breaking change for the GraphBinary format.
+            var enumValue = (string?) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+            if (enumValue == null) throw new IOException($"Read null as a value for {DataType}");
             return _readFunc.Invoke(enumValue);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/LambdaSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/LambdaSerializer.cs
index 7be1583..f017aee 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/LambdaSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/LambdaSerializer.cs
@@ -44,23 +44,23 @@
         protected override async Task WriteValueAsync(ILambda value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Language, stream, false, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(value.LambdaExpression, stream, false, cancellationToken)
+            await writer.WriteNonNullableValueAsync(value.Language, stream, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.LambdaExpression, stream, cancellationToken)
                 .ConfigureAwait(false);
-            await writer.WriteValueAsync(value.Arguments, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Arguments, stream, cancellationToken).ConfigureAwait(false);
         }
 
         /// <inheritdoc />
         protected override async Task<ILambda> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var language = (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken)
+            var language = (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken)
                 .ConfigureAwait(false);
-            var expression = (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken)
+            var expression = (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken)
                 .ConfigureAwait(false);
             
             // discard the arguments
-            await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
+            await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
 
             return new StringBasedLambda(expression, language);
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ListSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ListSerializer.cs
index 05f96e6..d586ecd 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ListSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/ListSerializer.cs
@@ -32,7 +32,7 @@
     /// A generic list serializer.
     /// </summary>
     /// <typeparam name="TMember">The type of elements in the list.</typeparam>
-    public class ListSerializer<TMember> : SimpleTypeSerializer<IList<TMember>>
+    public class ListSerializer<TMember> : SimpleTypeSerializer<IList<TMember?>>
     {
         /// <summary>
         ///     Initializes a new instance of the <see cref="ListSerializer{TList}" /> class.
@@ -42,10 +42,10 @@
         }
 
         /// <inheritdoc />
-        protected override async Task WriteValueAsync(IList<TMember> value, Stream stream, GraphBinaryWriter writer,
+        protected override async Task WriteValueAsync(IList<TMember?> value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Count, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Count, stream, cancellationToken).ConfigureAwait(false);
             
             foreach (var item in value)
             {
@@ -54,14 +54,14 @@
         }
 
         /// <inheritdoc />
-        protected override async Task<IList<TMember>> ReadValueAsync(Stream stream, GraphBinaryReader reader,
+        protected override async Task<IList<TMember?>> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var length = (int)await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
-            var result = new List<TMember>(length);
+            var length = (int)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
+            var result = new List<TMember?>(length);
             for (var i = 0; i < length; i++)
             {
-                result.Add((TMember) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false));
+                result.Add((TMember?) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false));
             }
 
             return result;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/MapSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/MapSerializer.cs
index d22526f..868155f 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/MapSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/MapSerializer.cs
@@ -33,7 +33,7 @@
     /// </summary>
     /// <typeparam name="TKey">The type of keys in the dictionary.</typeparam>
     /// <typeparam name="TValue">The type of values in the dictionary.</typeparam>
-    public class MapSerializer<TKey, TValue> : SimpleTypeSerializer<IDictionary<TKey, TValue>>
+    public class MapSerializer<TKey, TValue> : SimpleTypeSerializer<IDictionary<TKey, TValue?>> where TKey : notnull
     {
         /// <summary>
         ///     Initializes a new instance of the <see cref="MapSerializer{TKey, TValue}" /> class.
@@ -43,10 +43,10 @@
         }
 
         /// <inheritdoc />
-        protected override async Task WriteValueAsync(IDictionary<TKey, TValue> value, Stream stream,
+        protected override async Task WriteValueAsync(IDictionary<TKey, TValue?> value, Stream stream,
             GraphBinaryWriter writer, CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Count, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Count, stream, cancellationToken).ConfigureAwait(false);
 
             foreach (var key in value.Keys)
             {
@@ -56,16 +56,17 @@
         }
 
         /// <inheritdoc />
-        protected override async Task<IDictionary<TKey, TValue>> ReadValueAsync(Stream stream, GraphBinaryReader reader,
+        protected override async Task<IDictionary<TKey, TValue?>> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
             var length = await stream.ReadIntAsync(cancellationToken).ConfigureAwait(false);
-            var result = new Dictionary<TKey, TValue>(length);
+            var result = new Dictionary<TKey, TValue?>(length);
             
             for (var i = 0; i < length; i++)
             {
-                var key = (TKey) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
-                var value = (TValue) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+                var key = (TKey?) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+                if (key == null) throw new IOException("Read null as the key for a dictionary.");
+                var value = (TValue?) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
                 result.Add(key, value);
             }
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PSerializer.cs
index 4579c6a..d3cbddc 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PSerializer.cs
@@ -23,6 +23,7 @@
 
 using System.Collections;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using System.Threading;
 using System.Threading.Tasks;
@@ -50,8 +51,8 @@
 
             var argsLength = value.Other == null ? args.Count : args.Count + 1;
 
-            await writer.WriteValueAsync(value.OperatorName, stream, false, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(argsLength, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.OperatorName, stream, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(argsLength, stream, cancellationToken).ConfigureAwait(false);
 
             foreach (var arg in args)
             {
@@ -68,12 +69,12 @@
         protected override async Task<P> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var operatorName = (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken)
+            var operatorName = (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken)
                 .ConfigureAwait(false);
             var argsLength =
-                (int)await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
+                (int)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
 
-            var args = new object[argsLength];
+            var args = new object?[argsLength];
             for (var i = 0; i < argsLength; i++)
             {
                 args[i] = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
@@ -82,23 +83,30 @@
             if (operatorName == "and" || operatorName == "or")
             {
                 
-                return new P(operatorName, (P) args[0], (P) args[1]);
+                return new P(operatorName, SafelyCastToP(args[0]), SafelyCastToP(args[1]));
             }
 
             if (operatorName == "not")
             {
-                return new P(operatorName, (P) args[0]);
+                return new P(operatorName, SafelyCastToP(args[0]));
             }
 
             if (argsLength == 1)
             {
                 if (DataType == DataType.TextP)
                 {
-                    return new TextP(operatorName, (string) args[0]);
+                    return new TextP(operatorName,
+                        (string?) args[0] ?? throw new IOException("Read null but expected a string"));
                 }
                 return new P(operatorName, args[0]);
             }
             return new P(operatorName, args);
         }
+        
+        private static P SafelyCastToP([NotNull] object? pObject)
+        {
+            if (pObject == null) throw new IOException("Read null but expected P");
+            return (P) pObject;
+        }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PathSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PathSerializer.cs
index a9aba98..fa02d5d 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PathSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PathSerializer.cs
@@ -53,7 +53,8 @@
             CancellationToken cancellationToken = default)
         {
             var readLabelObjects =
-                (List<object>)await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+                (List<object>?)await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+            if (readLabelObjects == null) throw new IOException("Read null, but expected a list of labels");
             var labels = new List<ISet<string>>();
             foreach (var labelObjectList in readLabelObjects)
             {
@@ -65,8 +66,8 @@
                 labels.Add(labelSet);
             }
             
-            var objects = (List<object>) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
-            
+            var objects = (List<object?>?) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+            if (objects == null) throw new IOException("Read null, but expected a list of objects");
             return new Path(labels, objects);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PropertySerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PropertySerializer.cs
index 08fc6e9..556cd91 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PropertySerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/PropertySerializer.cs
@@ -30,7 +30,8 @@
     /// <summary>
     /// A <see cref="Property"/> serializer.
     /// </summary>
-    public class PropertySerializer : SimpleTypeSerializer<Property>
+    public class 
+        PropertySerializer : SimpleTypeSerializer<Property>
     {
         /// <summary>
         ///     Initializes a new instance of the <see cref="PropertySerializer" /> class.
@@ -43,7 +44,7 @@
         protected override async Task WriteValueAsync(Property value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Key, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Key, stream, cancellationToken).ConfigureAwait(false);
             await writer.WriteAsync(value.Value, stream, cancellationToken).ConfigureAwait(false);
             
             // placeholder for the parent element
@@ -55,7 +56,7 @@
             CancellationToken cancellationToken = default)
         {
             var p = new Property(
-                (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken).ConfigureAwait(false),
+                (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken).ConfigureAwait(false),
                 await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false));
 
             // discard parent element
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SetSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SetSerializer.cs
index 8983a4c..92a3ddd 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SetSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SetSerializer.cs
@@ -36,7 +36,7 @@
     /// <typeparam name="TSet">The type of the set to serialize.</typeparam>
     /// <typeparam name="TMember">The type of elements in the set.</typeparam>
     public class SetSerializer<TSet, TMember> : SimpleTypeSerializer<TSet>
-        where TSet : ISet<TMember>, new()
+        where TSet : ISet<TMember?>, new()
     {
         /// <summary>
         ///     Initializes a new instance of the <see cref="SetSerializer{TSet,TMember}" /> class.
@@ -52,7 +52,7 @@
             var enumerable = (IEnumerable) value;
             var list = enumerable.Cast<object>().ToList();
 
-            await writer.WriteValueAsync(list.Count, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(list.Count, stream, cancellationToken).ConfigureAwait(false);
             
             foreach (var item in list)
             {
@@ -64,11 +64,11 @@
         protected override async Task<TSet> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var length = (int)await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
+            var length = (int)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
             var result = new TSet();
             for (var i = 0; i < length; i++)
             {
-                result.Add((TMember) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false));
+                result.Add((TMember?) await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false));
             }
 
             return result;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SimpleTypeSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SimpleTypeSerializer.cs
index cf6aa7b..172fbe7 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SimpleTypeSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/SimpleTypeSerializer.cs
@@ -46,34 +46,33 @@
         public DataType DataType { get; }
 
         /// <inheritdoc />
-        public async Task WriteAsync(object value, Stream stream, GraphBinaryWriter writer,
+        public async Task WriteAsync(object? value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await WriteValueAsync((T) value, stream, writer, true, cancellationToken).ConfigureAwait(false);
+            await WriteNullableValueAsync((T?) value, stream, writer, cancellationToken).ConfigureAwait(false);
         }
 
         /// <inheritdoc />
-        public async Task WriteValueAsync(object value, Stream stream, GraphBinaryWriter writer, bool nullable,
+        public async Task WriteNullableValueAsync(object? value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
             if (value == null)
             {
-                if (!nullable)
-                {
-                    throw new IOException("Unexpected null value when nullable is false");
-                }
-
                 await writer.WriteValueFlagNullAsync(stream, cancellationToken).ConfigureAwait(false);
                 return;
             }
 
-            if (nullable)
-            {
-                await writer.WriteValueFlagNoneAsync(stream, cancellationToken).ConfigureAwait(false);
-            }
+            await writer.WriteValueFlagNoneAsync(stream, cancellationToken).ConfigureAwait(false);
 
             await WriteValueAsync((T) value, stream, writer, cancellationToken).ConfigureAwait(false);
         }
+        
+        /// <inheritdoc />
+        public async Task WriteNonNullableValueAsync(object value, Stream stream, GraphBinaryWriter writer,
+            CancellationToken cancellationToken = default)
+        {
+            await WriteValueAsync((T) value, stream, writer, cancellationToken).ConfigureAwait(false);
+        }
 
         /// <summary>
         /// Writes a non-nullable value into a stream.
@@ -87,27 +86,31 @@
             CancellationToken cancellationToken = default);
 
         /// <inheritdoc />
-        public async Task<object> ReadAsync(Stream stream, GraphBinaryReader reader,
+        public async Task<object?> ReadAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            return await ReadValueAsync(stream, reader, true, cancellationToken).ConfigureAwait(false);
+            return await ReadNullableValueAsync(stream, reader, cancellationToken).ConfigureAwait(false);
         }
 
         /// <inheritdoc />
-        public async Task<object> ReadValueAsync(Stream stream, GraphBinaryReader reader, bool nullable,
+        public async Task<object?> ReadNullableValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            if (nullable)
+            var valueFlag = await stream.ReadByteAsync(cancellationToken).ConfigureAwait(false);
+            if ((valueFlag & 1) == 1)
             {
-                var valueFlag = await stream.ReadByteAsync(cancellationToken).ConfigureAwait(false);
-                if ((valueFlag & 1) == 1)
-                {
-                    return null;
-                }
+                return null;
             }
 
             return await ReadValueAsync(stream, reader, cancellationToken).ConfigureAwait(false);
         }
+        
+        /// <inheritdoc />
+        public async Task<object> ReadNonNullableValueAsync(Stream stream, GraphBinaryReader reader,
+            CancellationToken cancellationToken = default)
+        {
+            return (await ReadValueAsync(stream, reader, cancellationToken).ConfigureAwait(false))!;
+        }
 
         /// <summary>
         /// Reads a non-nullable value according to the type format.
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/StringSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/StringSerializer.cs
index ae2b9a1..034230a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/StringSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/StringSerializer.cs
@@ -45,7 +45,7 @@
             CancellationToken cancellationToken = default)
         {
             var bytes = Encoding.UTF8.GetBytes(value);
-            await writer.WriteValueAsync(bytes.Length, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(bytes.Length, stream, cancellationToken).ConfigureAwait(false);
             await stream.WriteAsync(bytes, cancellationToken).ConfigureAwait(false);
         }
 
@@ -53,7 +53,7 @@
         protected override async Task<string> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var length = (int)await reader.ReadValueAsync<int>(stream, false, cancellationToken).ConfigureAwait(false);
+            var length = (int)await reader.ReadNonNullableValueAsync<int>(stream, cancellationToken).ConfigureAwait(false);
             var bytes = new byte[length];
             await stream.ReadAsync(bytes, 0, length, cancellationToken).ConfigureAwait(false);
             return Encoding.UTF8.GetString(bytes);
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraversalSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraversalSerializer.cs
index 0b6ba0a..1e00047 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraversalSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraversalSerializer.cs
@@ -45,7 +45,7 @@
         protected override async Task WriteValueAsync(ITraversal value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Bytecode, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Bytecode, stream, cancellationToken).ConfigureAwait(false);
         }
 
         /// <summary>
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraversalStrategySerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraversalStrategySerializer.cs
index 6d7f537..24077fa 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraversalStrategySerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraversalStrategySerializer.cs
@@ -45,9 +45,9 @@
         protected override async Task WriteValueAsync(AbstractTraversalStrategy value, Stream stream,
             GraphBinaryWriter writer, CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(GremlinType.FromFqcn(value.Fqcn), stream, false, cancellationToken)
+            await writer.WriteNonNullableValueAsync(GremlinType.FromFqcn(value.Fqcn), stream, cancellationToken)
                 .ConfigureAwait(false);
-            await writer.WriteValueAsync(value.Configuration, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Configuration, stream, cancellationToken).ConfigureAwait(false);
         }
 
         /// <summary>
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraverserSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraverserSerializer.cs
index 12ba016..9be8a0c 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraverserSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TraverserSerializer.cs
@@ -44,7 +44,7 @@
         protected override async Task WriteValueAsync(Traverser value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
-            await writer.WriteValueAsync(value.Bulk, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Bulk, stream, cancellationToken).ConfigureAwait(false);
             await writer.WriteAsync(value.Object, stream, cancellationToken).ConfigureAwait(false);
         }
 
@@ -52,7 +52,7 @@
         protected override async Task<Traverser> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var bulk = (long)await reader.ReadValueAsync<long>(stream, false, cancellationToken).ConfigureAwait(false);
+            var bulk = (long)await reader.ReadNonNullableValueAsync<long>(stream, cancellationToken).ConfigureAwait(false);
             var v = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
             return new Traverser(v, bulk);
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TypeSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TypeSerializer.cs
index c02ba0e..51793da 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TypeSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/TypeSerializer.cs
@@ -48,8 +48,10 @@
         {
             if (typeof(AbstractTraversalStrategy).IsAssignableFrom(value))
             {
-                var strategyInstance = (AbstractTraversalStrategy) Activator.CreateInstance(value);
-                await writer.WriteValueAsync(strategyInstance.Fqcn, stream, false, cancellationToken)
+                var strategyInstance = (AbstractTraversalStrategy?)Activator.CreateInstance(value) ??
+                                       throw new IOException(
+                                           $"Cannot write the strategy {value} because an instance of that strategy could not be created");
+                await writer.WriteNonNullableValueAsync(strategyInstance.Fqcn, stream, cancellationToken)
                     .ConfigureAwait(false);
             }
             else
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/VertexPropertySerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/VertexPropertySerializer.cs
index bc146dc..f347e0a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/VertexPropertySerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/VertexPropertySerializer.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System.Collections.Generic;
 using System.IO;
 using System.Threading;
 using System.Threading.Tasks;
@@ -44,7 +45,7 @@
             CancellationToken cancellationToken = default)
         {
             await writer.WriteAsync(value.Id, stream, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(value.Label, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Label, stream, cancellationToken).ConfigureAwait(false);
             await writer.WriteAsync(value.Value, stream, cancellationToken).ConfigureAwait(false);
             
             // placeholder for the parent vertex
@@ -52,24 +53,24 @@
             
             // placeholder for properties
             await writer.WriteAsync(null, stream, cancellationToken).ConfigureAwait(false);
-
         }
 
         /// <inheritdoc />
         protected override async Task<VertexProperty> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            var vp = new VertexProperty(await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false),
-                (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken).ConfigureAwait(false),
-                await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false));
+            var id = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+            var label = (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken)
+                .ConfigureAwait(false);
+            var value = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
 
             // discard the parent vertex
             await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
-            
-            // discard the properties
-            await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
-            
-            return vp;
+
+            var properties = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+            var propertiesAsArray = (properties as List<object>)?.ToArray();
+
+            return new VertexProperty(id, label, value, null, propertiesAsArray);
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/VertexSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/VertexSerializer.cs
index c656431..0dd492c 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/VertexSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary/Types/VertexSerializer.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System.Collections.Generic;
 using System.IO;
 using System.Threading;
 using System.Threading.Tasks;
@@ -44,7 +45,7 @@
             CancellationToken cancellationToken = default)
         {
             await writer.WriteAsync(value.Id, stream, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(value.Label, stream, false, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(value.Label, stream, cancellationToken).ConfigureAwait(false);
             await writer.WriteAsync(null, stream, cancellationToken).ConfigureAwait(false);
         }
 
@@ -52,13 +53,13 @@
         protected override async Task<Vertex> ReadValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
+            var id = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+            var label = (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken).ConfigureAwait(false);
 
-            var v = new Vertex(await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false),
-                (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken).ConfigureAwait(false));
-            
-            // discard properties
-            await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
-            return v;
+            var properties = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false);
+            var propertiesAsArray = (properties as List<object>)?.ToArray();
+
+            return new Vertex(id, label, propertiesAsArray);
         }
     }
 }
\ No newline at end of file
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 a3f1ff6..36ea1fd 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BigIntegerDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BigIntegerDeserializer.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System.IO;
 using System.Numerics;
 using System.Text.Json;
 
@@ -31,6 +32,7 @@
         public dynamic Objectify(JsonElement graphson, GraphSONReader reader)
         {
             var bigInteger = graphson.ValueKind == JsonValueKind.String ? graphson.GetString() : graphson.GetRawText();
+            if (bigInteger == null) throw new IOException("Read null, but expected a BigInteger string representation");
             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 539224a..8f876b6 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BulkSetSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/BulkSetSerializer.cs
@@ -42,7 +42,7 @@
             // previous versions.
             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();
+                    (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 0feb3a2..adb4efa 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ByteBufferDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ByteBufferDeserializer.cs
@@ -21,6 +21,7 @@
 #endregion
 
 using System;
+using System.IO;
 using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
@@ -30,7 +31,8 @@
         public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
             var base64String = graphsonObject.GetString();
-            return Convert.FromBase64String(base64String);
+            return Convert.FromBase64String(base64String ??
+                                            throw new IOException("Read null but expected a base64 byte string"));
         }
     }
 }
\ 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 0c3e539..b86cf15 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/CharConverter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/CharConverter.cs
@@ -20,6 +20,7 @@
  */
 #endregion
 
+using System.IO;
 using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
@@ -31,7 +32,7 @@
         protected override bool StringifyValue => true;
         protected override dynamic FromJsonElement(JsonElement graphson)
         {
-            var deserializedByte = graphson.GetString();
+            var deserializedByte = graphson.GetString() ?? throw new IOException("Read null but expected a string");
             return deserializedByte[0];
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ClassSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ClassSerializer.cs
index 39d1abe..8bd7353 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ClassSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ClassSerializer.cs
@@ -23,6 +23,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.IO;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
@@ -31,7 +32,8 @@
         public Dictionary<string, dynamic> Dictify(dynamic objectData, GraphSONWriter writer)
         {
             var type = (Type) objectData;
-            return writer.ToDict(Activator.CreateInstance(type));
+            return writer.ToDict(Activator.CreateInstance(type) ??
+                                 throw new IOException($"Cannot write {objectData}. maybe it is not a supported type"));
         }
     }
 }
\ No newline at end of file
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 f195522..b4167a6 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DecimalConverter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DecimalConverter.cs
@@ -22,6 +22,7 @@
 #endregion
 
 using System.Globalization;
+using System.IO;
 using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
@@ -35,7 +36,9 @@
         {
             if (graphson.ValueKind == JsonValueKind.String)
             {
-                return decimal.Parse(graphson.GetString(), CultureInfo.InvariantCulture);
+                return decimal.Parse(
+                    graphson.GetString() ?? throw new IOException("Read null but expected a decimal string"),
+                    CultureInfo.InvariantCulture);
             }
             return graphson.GetDecimal();
         }
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 34d4f61..6835169 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DirectionDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DirectionDeserializer.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System.IO;
 using System.Text.Json;
 using Gremlin.Net.Process.Traversal;
 
@@ -30,7 +31,9 @@
     {
         public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            return Direction.GetByValue(graphsonObject.GetString());
+            return Direction.GetByValue(graphsonObject.GetString() ??
+                                        throw new IOException(
+                                            $"Read null but expected a {nameof(Direction)} string representation"));
         }
     }
 }
\ 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 2c1d17f..e23c7a5 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DurationDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/DurationDeserializer.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System.IO;
 using System.Text.Json;
 using System.Xml;
 
@@ -31,7 +32,9 @@
         public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
             var duration = graphsonObject.GetString();
-            return XmlConvert.ToTimeSpan(duration);
+            return XmlConvert.ToTimeSpan(duration ??
+                                         throw new IOException(
+                                             "Read null but expected a Duration string representation"));
         }
     }
 }
\ No newline at end of file
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 13f4ce0..758b1f8 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/EdgeDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/EdgeDeserializer.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System.Linq;
 using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
@@ -43,7 +44,16 @@
             var edgeLabel = graphsonObject.TryGetProperty("label", out var labelProperty)
                 ? labelProperty.GetString()
                 : "edge";
-            return new Edge(edgeId, outV, edgeLabel, inV);
+
+            dynamic?[]? properties = null;
+            if (graphsonObject.TryGetProperty("properties", out var propertiesObject)
+                && propertiesObject.ValueKind == JsonValueKind.Object)
+            {
+                properties = propertiesObject.EnumerateObject()
+                    .Select(p => reader.ToObject(p.Value)).ToArray();
+            }
+
+            return new Edge(edgeId, outV, edgeLabel, inV, properties);
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSON2MessageSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSON2MessageSerializer.cs
index c0c36b1..7f9d7bd 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSON2MessageSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSON2MessageSerializer.cs
@@ -35,7 +35,7 @@
         /// </summary>
         /// <param name="graphSONReader">The <see cref="GraphSON2Reader"/> used to deserialize from GraphSON.</param>
         /// <param name="graphSONWriter">The <see cref="GraphSON2Writer"/> used to serialize to GraphSON.</param>
-        public GraphSON2MessageSerializer(GraphSON2Reader graphSONReader = null, GraphSON2Writer graphSONWriter = null)
+        public GraphSON2MessageSerializer(GraphSON2Reader? graphSONReader = null, GraphSON2Writer? graphSONWriter = null)
             : base(MimeType, graphSONReader ?? new GraphSON2Reader(), graphSONWriter ?? new GraphSON2Writer())
         {
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSON3MessageSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSON3MessageSerializer.cs
index abb6a75..bc434c7 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSON3MessageSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSON3MessageSerializer.cs
@@ -35,7 +35,7 @@
         /// </summary>
         /// <param name="graphSONReader">The <see cref="GraphSON3Reader"/> used to deserialize from GraphSON.</param>
         /// <param name="graphSONWriter">The <see cref="GraphSON3Writer"/> used to serialize to GraphSON.</param>
-        public GraphSON3MessageSerializer(GraphSON3Reader graphSONReader = null, GraphSON3Writer graphSONWriter = null)
+        public GraphSON3MessageSerializer(GraphSON3Reader? graphSONReader = null, GraphSON3Writer? graphSONWriter = null)
             : base(MimeType, graphSONReader ?? new GraphSON3Reader(), graphSONWriter ?? new GraphSON3Writer())
         {
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONMessageSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONMessageSerializer.cs
index 4d4ffa1..c9f2b88 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONMessageSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONMessageSerializer.cs
@@ -23,6 +23,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.IO;
 using System.Text;
 using System.Text.Json;
 using System.Threading;
@@ -72,17 +73,17 @@
         }
 
         /// <inheritdoc />
-        public virtual Task<ResponseMessage<List<object>>> DeserializeMessageAsync(byte[] message,
+        public virtual Task<ResponseMessage<List<object>>?> DeserializeMessageAsync(byte[] message,
             CancellationToken cancellationToken = default)
         {
             if (message == null) throw new ArgumentNullException(nameof(message));
             if (cancellationToken.CanBeCanceled) cancellationToken.ThrowIfCancellationRequested();
-            if (message.Length == 0) return Task.FromResult<ResponseMessage<List<object>>>(null);
+            if (message.Length == 0) return Task.FromResult<ResponseMessage<List<object>>?>(null);
             
             var reader = new Utf8JsonReader(message);
             var responseMessage =
                 JsonSerializer.Deserialize<ResponseMessage<JsonElement>>(ref reader, JsonDeserializingOptions);
-            if (responseMessage == null) return Task.FromResult<ResponseMessage<List<object>>>(null);;
+            if (responseMessage == null) return Task.FromResult<ResponseMessage<List<object>>?>(null);
             
             var data = _graphSONReader.ToObject(responseMessage.Result.Data);
             return Task.FromResult(CopyMessageWithNewData(responseMessage, data));
@@ -91,16 +92,9 @@
         private static ResponseMessage<List<object>> CopyMessageWithNewData(ResponseMessage<JsonElement> origMsg,
             dynamic data)
         {
-            return new ResponseMessage<List<object>>
-            {
-                RequestId = origMsg.RequestId,
-                Status = origMsg.Status,
-                Result = new ResponseResult<List<object>>
-                {
-                    Data = data == null ? null : new List<object>(data),
-                    Meta = origMsg.Result.Meta
-                }
-            };
+            var result = new ResponseResult<List<object>>(data == null ? null : new List<object>(data),
+                origMsg.Result.Meta);
+            return new ResponseMessage<List<object>>(origMsg.RequestId, origMsg.Status, result);
         }
     }
 }
\ 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 3208966..3e09ec3 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONReader.cs
@@ -23,6 +23,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
 using System.Text.Json;
 
@@ -36,35 +37,34 @@
         /// <summary>
         /// Contains the <see cref="IGraphSONDeserializer" /> instances by their type identifier. 
         /// </summary>
-        protected readonly Dictionary<string, IGraphSONDeserializer> Deserializers = new Dictionary
-            <string, IGraphSONDeserializer>
-            {
-                {"g:Traverser", new TraverserReader()},
-                {"g:Int32", new Int32Converter()},
-                {"g:Int64", new Int64Converter()},
-                {"g:Float", new FloatConverter()},
-                {"g:Double", new DoubleConverter()},
-                {"g:Direction", new DirectionDeserializer()},
-                {"g:Merge", new MergeDeserializer()},
-                {"g:UUID", new UuidDeserializer()},
-                {"g:Date", new DateDeserializer()},
-                {"g:Timestamp", new DateDeserializer()},
-                {"g:Vertex", new VertexDeserializer()},
-                {"g:Edge", new EdgeDeserializer()},
-                {"g:Property", new PropertyDeserializer()},
-                {"g:VertexProperty", new VertexPropertyDeserializer()},
-                {"g:Path", new PathDeserializer()},
-                {"g:T", new TDeserializer()},
+        protected readonly Dictionary<string, IGraphSONDeserializer> Deserializers = new()
+        {
+            { "g:Traverser", new TraverserReader() },
+            { "g:Int32", new Int32Converter() },
+            { "g:Int64", new Int64Converter() },
+            { "g:Float", new FloatConverter() },
+            { "g:Double", new DoubleConverter() },
+            { "g:Direction", new DirectionDeserializer() },
+            { "g:Merge", new MergeDeserializer() },
+            { "g:UUID", new UuidDeserializer() },
+            { "g:Date", new DateDeserializer() },
+            { "g:Timestamp", new DateDeserializer() },
+            { "g:Vertex", new VertexDeserializer() },
+            { "g:Edge", new EdgeDeserializer() },
+            { "g:Property", new PropertyDeserializer() },
+            { "g:VertexProperty", new VertexPropertyDeserializer() },
+            { "g:Path", new PathDeserializer() },
+            { "g:T", new TDeserializer() },
 
-                //Extended
-                {"gx:BigDecimal", new DecimalConverter()},
-                {"gx:Duration", new DurationDeserializer()},
-                {"gx:BigInteger", new BigIntegerDeserializer()},
-                {"gx:Byte", new ByteConverter()},
-                {"gx:ByteBuffer", new ByteBufferDeserializer()},
-                {"gx:Char", new CharConverter()},
-                {"gx:Int16", new Int16Converter() }
-            };
+            //Extended
+            { "gx:BigDecimal", new DecimalConverter() },
+            { "gx:Duration", new DurationDeserializer() },
+            { "gx:BigInteger", new BigIntegerDeserializer() },
+            { "gx:Byte", new ByteConverter() },
+            { "gx:ByteBuffer", new ByteBufferDeserializer() },
+            { "gx:Char", new CharConverter() },
+            { "gx:Int16", new Int16Converter() }
+        };
 
         /// <summary>
         ///     Initializes a new instance of the <see cref="GraphSONReader" /> class.
@@ -101,7 +101,7 @@
         /// </summary>
         /// <param name="graphSon">The GraphSON to deserialize.</param>
         /// <returns>The deserialized object.</returns>
-        public virtual dynamic ToObject(JsonElement graphSon)
+        public virtual dynamic? ToObject(JsonElement graphSon)
         {
             switch (graphSon.ValueKind)
             {
@@ -124,7 +124,9 @@
 
             if (graphSon.TryGetProperty(GraphSONTokens.TypeKey, out var graphSonTypeProperty))
             {
-                return ReadValueOfType(graphSon, graphSonTypeProperty.GetString());
+                return ReadValueOfType(graphSon,
+                    graphSonTypeProperty.GetString() ??
+                    throw new IOException("Read GraphSON type key is not a string"));
             }
             return ReadDictionary(graphSon);
             
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 e453efc..5b1725f 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/GraphSONWriter.cs
@@ -24,6 +24,7 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Numerics;
 using System.Text.Encodings.Web;
@@ -39,45 +40,44 @@
     /// </summary>
     public abstract class GraphSONWriter
     {
-        private static readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions
-            {Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping};
-        
+        private static readonly JsonSerializerOptions JsonOptions = new()
+            { Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping };
+
         /// <summary>
         /// Contains the information of serializers by type.
         /// </summary>
-        protected readonly Dictionary<Type, IGraphSONSerializer> Serializers = new Dictionary
-            <Type, IGraphSONSerializer>
-            {
-                {typeof(ITraversal), new TraversalSerializer()},
-                {typeof(Bytecode), new BytecodeSerializer()},
-                {typeof(Binding), new BindingSerializer()},
-                {typeof(RequestMessage), new RequestMessageSerializer()},
-                {typeof(int), new Int32Converter()},
-                {typeof(long), new Int64Converter()},
-                {typeof(float), new FloatConverter()},
-                {typeof(double), new DoubleConverter()},
-                {typeof(Guid), new UuidSerializer()},
-                {typeof(DateTimeOffset), new DateSerializer()},
-                {typeof(Type), new ClassSerializer()},
-                {typeof(EnumWrapper), new EnumSerializer()},
-                {typeof(P), new PSerializer()},
-                {typeof(TextP), new TextPSerializer()},
-                {typeof(Vertex), new VertexSerializer()},
-                {typeof(Edge), new EdgeSerializer()},
-                {typeof(Property), new PropertySerializer()},
-                {typeof(VertexProperty), new VertexPropertySerializer()},
-                {typeof(AbstractTraversalStrategy), new TraversalStrategySerializer()},
-                {typeof(ILambda), new LambdaSerializer()},
+        protected readonly Dictionary<Type, IGraphSONSerializer> Serializers = new()
+        {
+            { typeof(ITraversal), new TraversalSerializer() },
+            { typeof(Bytecode), new BytecodeSerializer() },
+            { typeof(Binding), new BindingSerializer() },
+            { typeof(RequestMessage), new RequestMessageSerializer() },
+            { typeof(int), new Int32Converter() },
+            { typeof(long), new Int64Converter() },
+            { typeof(float), new FloatConverter() },
+            { typeof(double), new DoubleConverter() },
+            { typeof(Guid), new UuidSerializer() },
+            { typeof(DateTimeOffset), new DateSerializer() },
+            { typeof(Type), new ClassSerializer() },
+            { typeof(EnumWrapper), new EnumSerializer() },
+            { typeof(P), new PSerializer() },
+            { typeof(TextP), new TextPSerializer() },
+            { typeof(Vertex), new VertexSerializer() },
+            { typeof(Edge), new EdgeSerializer() },
+            { typeof(Property), new PropertySerializer() },
+            { typeof(VertexProperty), new VertexPropertySerializer() },
+            { typeof(AbstractTraversalStrategy), new TraversalStrategySerializer() },
+            { typeof(ILambda), new LambdaSerializer() },
 
-                //Extended
-                {typeof(decimal), new DecimalConverter()},
-                {typeof(TimeSpan), new DurationSerializer()},
-                {typeof(BigInteger), new BigIntegerSerializer()},
-                {typeof(byte), new ByteConverter()},
-                {typeof(byte[]), new ByteBufferSerializer()},
-                {typeof(char), new CharConverter() },
-                {typeof(short), new Int16Converter() }
-            };
+            //Extended
+            { typeof(decimal), new DecimalConverter() },
+            { typeof(TimeSpan), new DurationSerializer() },
+            { typeof(BigInteger), new BigIntegerSerializer() },
+            { typeof(byte), new ByteConverter() },
+            { typeof(byte[]), new ByteBufferSerializer() },
+            { typeof(char), new CharConverter() },
+            { typeof(short), new Int16Converter() }
+        };
 
         /// <summary>
         ///     Initializes a new instance of the <see cref="GraphSONWriter" /> class.
@@ -106,7 +106,7 @@
         /// <returns>The serialized GraphSON.</returns>
         public virtual string WriteObject(dynamic objectData)
         {
-            return JsonSerializer.Serialize(ToDict(objectData), _jsonOptions);
+            return JsonSerializer.Serialize(ToDict(objectData), JsonOptions);
         }
 
         /// <summary>
@@ -114,7 +114,8 @@
         /// </summary>
         /// <param name="objectData">The object to transform.</param>
         /// <returns>A GraphSON representation of the object ready to be serialized.</returns>
-        public dynamic ToDict(dynamic objectData)
+        [return: NotNullIfNotNull("objectData")]
+        public dynamic? ToDict(dynamic? objectData)
         {
             if (objectData != null)
             {
@@ -132,7 +133,7 @@
             return objectData;         
         }
 
-        private IGraphSONSerializer TryGetSerializerFor(Type type)
+        private IGraphSONSerializer? TryGetSerializerFor(Type type)
         {
             if (Serializers.ContainsKey(type))
             {
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 add8eb5..154010a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ListSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/ListSerializer.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System;
 using System.Collections.Generic;
 using System.Text.Json;
 
@@ -28,7 +29,7 @@
 {
     internal class ListSerializer : IGraphSONDeserializer, IGraphSONSerializer
     {
-        private static readonly IReadOnlyList<object> EmptyList = new object[0];
+        private static readonly IReadOnlyList<object> EmptyList = Array.Empty<object>();
         
         public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
@@ -36,7 +37,7 @@
             {
                 return EmptyList;
             }
-            var result = new object[graphsonObject.GetArrayLength()];
+            var result = new object?[graphsonObject.GetArrayLength()];
             for (var i = 0; i < result.Length; i++)
             {
                 result[i] = reader.ToObject(graphsonObject[i]);
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 99165a7..3ba7e3a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MapSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MapSerializer.cs
@@ -36,7 +36,7 @@
             {
                 return new Dictionary<object, object>(0);
             }
-            var result = new Dictionary<object, object>(graphsonObject.GetArrayLength() / 2);
+            var result = new Dictionary<object, object?>(graphsonObject.GetArrayLength() / 2);
             for (var i = 0; i < graphsonObject.GetArrayLength(); i += 2)
             {
                 result[reader.ToObject(graphsonObject[i])] = reader.ToObject(graphsonObject[i + 1]);
@@ -51,7 +51,7 @@
             {
                 throw new InvalidOperationException("Object must implement IDictionary");
             }
-            var result = new object[map.Count * 2];
+            var result = new object?[map.Count * 2];
             var index = 0;
             foreach (var key in map.Keys)
             {
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MergeDeserializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MergeDeserializer.cs
index 26b6869..3a34eb9 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MergeDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/MergeDeserializer.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System.IO;
 using System.Text.Json;
 using Gremlin.Net.Process.Traversal;
 
@@ -30,7 +31,8 @@
     {
         public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            return Merge.GetByValue(graphsonObject.GetString());
+            return Merge.GetByValue(graphsonObject.GetString() ??
+                                    throw new IOException("Read null but expected a Merge value"));
         }
     }
 }
\ No newline at end of file
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 4492685..b12c494 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/NumberConverter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/NumberConverter.cs
@@ -27,7 +27,7 @@
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
-    internal abstract class NumberConverter<T> : IGraphSONDeserializer, IGraphSONSerializer
+    internal abstract class NumberConverter<T> : IGraphSONDeserializer, IGraphSONSerializer where T : notnull
     {
         protected abstract string GraphSONTypeName { get; }
         protected virtual string Prefix => "g";
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 d05663b..6e35321 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Path3Deserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/Path3Deserializer.cs
@@ -22,6 +22,7 @@
 #endregion
 
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
 using System.Text.Json;
 
@@ -32,12 +33,14 @@
         public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
             // "labels" is a object[] where each item is ISet<object>
-            var labelProperty = (object[])reader.ToObject(graphsonObject.GetProperty("labels"));
+            var labelProperty = (object[]?)reader.ToObject(graphsonObject.GetProperty("labels"));
+            if (labelProperty == null) throw new IOException($"Could not read the labels for the {nameof(Path)}");
             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.GetProperty("objects"));
+            object?[] objects = reader.ToObject(graphsonObject.GetProperty("objects")) ??
+                               throw new IOException($"Could not read the objects for the {nameof(Path)}");
             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 3a37f66..baa9722 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PathDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PathDeserializer.cs
@@ -22,6 +22,7 @@
 #endregion
 
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
 using System.Text.Json;
 
@@ -34,7 +35,8 @@
             var labels =
                 graphsonObject.GetProperty("labels").EnumerateArray()
                     .Select(readObjLabels =>
-                        new HashSet<string>(readObjLabels.EnumerateArray().Select(l => l.GetString())))
+                        new HashSet<string>(readObjLabels.EnumerateArray().Select(l =>
+                            l.GetString() ?? throw new IOException("Read null but expected a Path label"))))
                     .ToList<ISet<string>>();
             var objects = graphsonObject.GetProperty("objects").EnumerateArray().Select(o => reader.ToObject(o))
                 .ToList();
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PropertySerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PropertySerializer.cs
index 0a7e6f8..d668442 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PropertySerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/PropertySerializer.cs
@@ -22,6 +22,7 @@
 #endregion
 
 using System.Collections.Generic;
+using System.IO;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
 {
@@ -40,23 +41,25 @@
             return GraphSONUtil.ToTypedValue(nameof(Property), valueDict);
         }
 
-        private dynamic CreateElementDict(Element element, GraphSONWriter writer)
+        private dynamic? CreateElementDict(Element? element, GraphSONWriter writer)
         {
             if (element == null)
                 return null;
             var serializedElement = writer.ToDict(element);
+            if (serializedElement == null)
+            {
+                throw new IOException(
+                    $"Could not write the {nameof(Property.Element)} of this {nameof(Property)}, {nameof(Property.Element)}: {element}");
+            }
             Dictionary<string, dynamic> elementDict = serializedElement;
             if (elementDict.ContainsKey(GraphSONTokens.ValueKey))
             {
                 var elementValueSerialized = elementDict[GraphSONTokens.ValueKey];
                 Dictionary<string, dynamic> elementValueDict = elementValueSerialized;
-                if (elementValueDict != null)
-                {
-                    elementValueDict.Remove("outVLabel");
-                    elementValueDict.Remove("inVLabel");
-                    elementValueDict.Remove("properties");
-                    elementValueDict.Remove("value");
-                }
+                elementValueDict.Remove("outVLabel");
+                elementValueDict.Remove("inVLabel");
+                elementValueDict.Remove("properties");
+                elementValueDict.Remove("value");
             }
             return serializedElement;
         }
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 590392e..fce7465 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/SetSerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/SetSerializer.cs
@@ -36,7 +36,7 @@
                 return new HashSet<object>();
             }
             // ISet<object>
-            return new HashSet<object>(graphsonObject.EnumerateArray().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 efbc542..270d36a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/TDeserializer.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System.IO;
 using System.Text.Json;
 using Gremlin.Net.Process.Traversal;
 
@@ -30,7 +31,8 @@
     {
         public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
-            return T.GetByValue(graphsonObject.GetString());
+            return T.GetByValue(graphsonObject.GetString()??
+                                throw new IOException($"Read null but expected a {nameof(T)} string representation"));
         }
     }
 }
\ No newline at end of file
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 58caac7..8e64236 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/UuidDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/UuidDeserializer.cs
@@ -22,6 +22,7 @@
 #endregion
 
 using System;
+using System.IO;
 using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
@@ -31,7 +32,7 @@
         public dynamic Objectify(JsonElement graphsonObject, GraphSONReader reader)
         {
             var uuidString = graphsonObject.GetString();
-
+            if (uuidString == null) throw new IOException("Read null but expected a GUID string representation");
             return Guid.Parse(uuidString);
         }
     }
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 72615ef..9590218 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexDeserializer.cs
@@ -21,6 +21,8 @@
 
 #endregion
 
+using System.Collections.Generic;
+using System.Linq;
 using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
@@ -33,7 +35,16 @@
             var label = graphsonObject.TryGetProperty("label", out var labelProperty)
                 ? labelProperty.GetString()
                 : Vertex.DefaultLabel;
-            return new Vertex(id, label);
+
+            dynamic?[]? properties = null;
+            if (graphsonObject.TryGetProperty("properties", out var propertiesObject)
+                && propertiesObject.ValueKind == JsonValueKind.Object)
+            {
+                properties = propertiesObject.EnumerateObject()
+                    .SelectMany(p => (reader.ToObject(p.Value) as IEnumerable<object>)!).ToArray();
+            }
+
+            return new Vertex(id, label, properties);
         }
     }
 }
\ No newline at end of file
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 15a99dc..b204185 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexPropertyDeserializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexPropertyDeserializer.cs
@@ -21,6 +21,7 @@
 
 #endregion
 
+using System.Linq;
 using System.Text.Json;
 
 namespace Gremlin.Net.Structure.IO.GraphSON
@@ -35,7 +36,15 @@
             var vertex = graphsonObject.TryGetProperty("vertex", out var vertexProperty)
                 ? new Vertex(reader.ToObject(vertexProperty))
                 : null;
-            return new VertexProperty(id, label, value, vertex);
+
+            dynamic?[]? properties = null;
+            if (graphsonObject.TryGetProperty("properties", out var propertiesObject)
+                && propertiesObject.ValueKind == JsonValueKind.Object)
+            {
+                properties = propertiesObject.EnumerateObject()
+                    .Select(p => new Property(p.Name, reader.ToObject(p.Value))).ToArray();
+            }
+            return new VertexProperty(id, label, value, vertex, properties);
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexPropertySerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexPropertySerializer.cs
index 12cc7ac..6000d35 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexPropertySerializer.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphSON/VertexPropertySerializer.cs
@@ -34,9 +34,12 @@
             {
                 {"id", writer.ToDict(vertexProperty.Id)},
                 {"label", vertexProperty.Label},
-                {"value", writer.ToDict(vertexProperty.Value)},
-                {"vertex", writer.ToDict(vertexProperty.Vertex.Id)}
+                {"value", writer.ToDict(vertexProperty.Value)}
             };
+            if (vertexProperty.Vertex != null)
+            {
+                valueDict.Add("vertex", writer.ToDict(vertexProperty.Vertex.Id));
+            }
             return GraphSONUtil.ToTypedValue(nameof(VertexProperty), valueDict);
         }
     }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/Path.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/Path.cs
index d205a88..682aad3 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/Path.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/Path.cs
@@ -24,6 +24,7 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using Gremlin.Net.Process.Traversal;
 
@@ -36,17 +37,17 @@
     ///     In abstraction, any Path implementation maintains two lists: a list of sets of labels and a list of objects.
     ///     The list of labels are the labels of the steps traversed. The list of objects are the objects traversed.
     /// </remarks>
-    public class Path : IReadOnlyList<object>, IEquatable<Path>
+    public class Path : IReadOnlyList<object?>, IEquatable<Path>
     {
         /// <summary>
         ///     Initializes a new instance of the <see cref="Path" /> class.
         /// </summary>
         /// <param name="labels">The labels associated with the path</param>
         /// <param name="objects">The objects in the <see cref="Path" />.</param>
-        public Path(IList<ISet<string>> labels, IList<object> objects)
+        public Path(IList<ISet<string>> labels, IList<object?> objects)
         {
-            Labels = labels;
-            Objects = objects;
+            Labels = labels ?? throw new ArgumentNullException(nameof(labels));
+            Objects = objects ?? throw new ArgumentNullException(nameof(objects));
         }
 
         /// <summary>
@@ -57,7 +58,7 @@
         /// <summary>
         ///     Gets an ordered list of the objects in the <see cref="Path" />.
         /// </summary>
-        public IList<object> Objects { get; }
+        public IList<object?> Objects { get; }
 
         /// <summary>
         ///     Gets the object associated with the particular label of the path.
@@ -70,15 +71,15 @@
         {
             get
             {
-                var objFound = TryGetValue(label, out object obj);
+                var objFound = TryGetValue(label, out var obj);
                 if (!objFound)
                     throw new KeyNotFoundException($"The step with label {label} does not exist");
-                return obj;
+                return obj!;
             }
         }
 
         /// <inheritdoc />
-        public bool Equals(Path other)
+        public bool Equals(Path? other)
         {
             if (ReferenceEquals(null, other)) return false;
             if (ReferenceEquals(this, other)) return true;
@@ -90,7 +91,7 @@
         /// </summary>
         /// <param name="index">The index of the path</param>
         /// <returns>The object associated with the index of the path</returns>
-        public dynamic this[int index] => Objects[index];
+        public dynamic? this[int index] => Objects[index];
 
         /// <summary>
         ///     Gets the number of steps in the path.
@@ -131,7 +132,7 @@
         /// <param name="label">The label of the path.</param>
         /// <param name="value">The object associated with the label of the path.</param>
         /// <returns>True, if an object was found for the label.</returns>
-        public bool TryGetValue(string label, out object value)
+        public bool TryGetValue(string label, [NotNullWhen(true)] out object? value)
         {
             value = null;
             for (var i = 0; i < Labels.Count; i++)
@@ -139,43 +140,38 @@
                 if (!Labels[i].Contains(label)) continue;
                 if (value == null)
                     value = Objects[i];
-                else if (value.GetType() == typeof(List<object>))
-                    ((List<object>) value).Add(Objects[i]);
+                else if (value.GetType() == typeof(List<object?>))
+                    ((List<object?>) value).Add(Objects[i]);
                 else
-                    value = new List<object> {value, Objects[i]};
+                    value = new List<object?> {value, Objects[i]};
             }
             return value != null;
         }
 
-        private bool ObjectsEqual(ICollection<object> otherObjects)
+        private bool ObjectsEqual(ICollection<object?> otherObjects)
         {
-            if (Objects == null)
-                return otherObjects == null;
             return Objects.SequenceEqual(otherObjects);
         }
 
         private bool LabelsEqual(ICollection<ISet<string>> otherLabels)
         {
-            if (Labels == null)
-                return otherLabels == null;
             if (Labels.Count != otherLabels.Count)
                 return false;
-            using (var enumOther = otherLabels.GetEnumerator())
-            using (var enumThis = Labels.GetEnumerator())
+            using var enumOther = otherLabels.GetEnumerator();
+            using var enumThis = Labels.GetEnumerator();
+            while (enumOther.MoveNext() && enumThis.MoveNext())
             {
-                while (enumOther.MoveNext() && enumThis.MoveNext())
+                if (!enumOther.Current.SequenceEqual(enumThis.Current))
                 {
-                    if (!enumOther.Current.SequenceEqual(enumThis.Current))
-                    {
-                        return false;
-                    }
+                    return false;
                 }
             }
+
             return true;
         }
 
         /// <inheritdoc />
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             if (ReferenceEquals(null, obj)) return false;
             if (ReferenceEquals(this, obj)) return true;
@@ -189,13 +185,12 @@
             unchecked
             {
                 var hashCode = 19;
-                if (Labels != null)
-                    hashCode = Labels.Where(objLabels => objLabels != null)
-                        .Aggregate(hashCode,
-                            (current1, objLabels) => objLabels.Aggregate(current1,
-                                (current, label) => current * 31 + label.GetHashCode()));
-                if (Objects != null)
-                    hashCode = Objects.Aggregate(hashCode, (current, obj) => current * 31 + obj.GetHashCode());
+                hashCode = Labels
+                    .Aggregate(hashCode,
+                        (current1, objLabels) => objLabels.Aggregate(current1,
+                            (current, label) => current * 31 + label.GetHashCode()));
+                hashCode = Objects.Aggregate(hashCode,
+                    (current, obj) => current * 31 + (obj == null ? 0 : obj.GetHashCode()));
                 return hashCode;
             }
         }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/Property.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/Property.cs
index b2adee7..291287d 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/Property.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/Property.cs
@@ -36,7 +36,7 @@
         /// <param name="key">The key of the property.</param>
         /// <param name="value">The value of the property.</param>
         /// <param name="element">The (optional) element that the property is associated with.</param>
-        public Property(string key, dynamic value, Element element = null)
+        public Property(string key, dynamic? value, Element? element = null)
         {
             Key = key;
             Value = value;
@@ -51,15 +51,15 @@
         /// <summary>
         ///     Gets the value of the property.
         /// </summary>
-        public dynamic Value { get; }
+        public dynamic? Value { get; }
 
         /// <summary>
         ///     Gets the element that this property is associated with.
         /// </summary>
-        public Element Element { get; }
+        public Element? Element { get; }
 
         /// <inheritdoc />
-        public bool Equals(Property other)
+        public bool Equals(Property? other)
         {
             if (ReferenceEquals(null, other)) return false;
             if (ReferenceEquals(this, other)) return true;
@@ -73,7 +73,7 @@
         }
 
         /// <inheritdoc />
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             if (ReferenceEquals(null, obj)) return false;
             if (ReferenceEquals(this, obj)) return true;
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/Vertex.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/Vertex.cs
index f667d26..c430dea 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/Vertex.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/Vertex.cs
@@ -21,6 +21,9 @@
 
 #endregion
 
+using System.Collections.Generic;
+using System.Linq;
+
 namespace Gremlin.Net.Structure
 {
     /// <summary>
@@ -38,11 +41,21 @@
         /// </summary>
         /// <param name="id">The id of the vertex.</param>
         /// <param name="label">The label of the vertex.</param>
-        public Vertex(object id, string label = DefaultLabel)
-            : base(id, label)
+        /// <param name="properties">Optional properties of the vertex.</param>
+        public Vertex(object? id, string label = DefaultLabel, dynamic[]? properties = null)
+            : base(id, label, properties)
         {
         }
 
+        /// <summary>
+        /// Get property by key
+        /// </summary>
+        /// <returns>property or null when not found</returns>
+        public VertexProperty? Property(string key)
+        {
+            return Properties?.Cast<VertexProperty>().FirstOrDefault(p => p.Key == key);
+        }
+
         /// <inheritdoc />
         public override string ToString()
         {
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/VertexProperty.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/VertexProperty.cs
index a8dd943..f8e211d 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/VertexProperty.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/VertexProperty.cs
@@ -21,6 +21,8 @@
 
 #endregion
 
+using System.Linq;
+
 namespace Gremlin.Net.Structure
 {
     /// <summary>
@@ -35,8 +37,9 @@
         /// <param name="label">The label of the vertex property.</param>
         /// <param name="value">The id of the vertex property.</param>
         /// <param name="vertex">The (optional) <see cref="Vertex" /> that owns this <see cref="VertexProperty" />.</param>
-        public VertexProperty(object id, string label, dynamic value, Vertex vertex = null)
-            : base(id, label)
+        /// <param name="properties">Optional properties of the VertexProperty.</param>
+        public VertexProperty(object? id, string label, dynamic? value, Vertex? vertex = null, dynamic[]? properties = null)
+            : base(id, label, properties)
         {
             Value = value;
             Vertex = vertex;
@@ -45,18 +48,27 @@
         /// <summary>
         ///     The value of this <see cref="VertexProperty" />.
         /// </summary>
-        public dynamic Value { get; }
+        public dynamic? Value { get; }
 
         /// <summary>
         ///     The <see cref="Vertex" /> that owns this <see cref="VertexProperty" />.
         /// </summary>
-        public Vertex Vertex { get; }
+        public Vertex? Vertex { get; }
 
         /// <summary>
         ///     The key of this <see cref="VertexProperty" />.
         /// </summary>
         public string Key => Label;
 
+        /// <summary>
+        /// Get property by key
+        /// </summary>
+        /// <returns>property or null when not found</returns>
+        public Property? Property(string key)
+        {
+            return Properties?.Cast<Property>().FirstOrDefault(p => p.Key == key);
+        }
+
         /// <inheritdoc />
         public override string ToString()
         {
diff --git a/gremlin-dotnet/src/pom.xml b/gremlin-dotnet/src/pom.xml
index 4813e7a..0ee6b9e 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.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-dotnet-source</artifactId>
     <name>Apache TinkerPop :: Gremlin.Net - Source</name>
@@ -38,7 +38,7 @@
                 <artifactId>gmavenplus-plugin</artifactId>
                 <dependencies>
                     <dependency>
-                        <groupId>org.codehaus.groovy</groupId>
+                        <groupId>org.apache.groovy</groupId>
                         <artifactId>groovy-all</artifactId>
                         <version>${groovy.version}</version>
                         <type>pom</type>
@@ -313,7 +313,7 @@
                                 <scope>runtime</scope>
                             </dependency>
                             <dependency>
-                                <groupId>org.codehaus.groovy</groupId>
+                                <groupId>org.apache.groovy</groupId>
                                 <artifactId>groovy-all</artifactId>
                                 <version>${groovy.version}</version>
                                 <type>pom</type>
diff --git a/gremlin-dotnet/test/Gremlin.Net.Benchmarks/Gremlin.Net.Benchmarks.csproj b/gremlin-dotnet/test/Gremlin.Net.Benchmarks/Gremlin.Net.Benchmarks.csproj
index 723184c..8c24a39 100644
--- a/gremlin-dotnet/test/Gremlin.Net.Benchmarks/Gremlin.Net.Benchmarks.csproj
+++ b/gremlin-dotnet/test/Gremlin.Net.Benchmarks/Gremlin.Net.Benchmarks.csproj
@@ -3,6 +3,7 @@
     <PropertyGroup>
         <OutputType>Exe</OutputType>
         <TargetFramework>net6.0</TargetFramework>
+        <Nullable>enable</Nullable>
     </PropertyGroup>
 
     <ItemGroup>
diff --git a/gremlin-dotnet/test/Gremlin.Net.Benchmarks/MessageSerializerBenchmarks.cs b/gremlin-dotnet/test/Gremlin.Net.Benchmarks/MessageSerializerBenchmarks.cs
index 500929a..45be90e 100644
--- a/gremlin-dotnet/test/Gremlin.Net.Benchmarks/MessageSerializerBenchmarks.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.Benchmarks/MessageSerializerBenchmarks.cs
@@ -86,22 +86,22 @@
                 .ConfigureAwait(false);
 
         [Benchmark]
-        public async Task<ResponseMessage<List<object>>> TestReadSmallResponseMessageBinary() =>
+        public async Task<ResponseMessage<List<object>>?> TestReadSmallResponseMessageBinary() =>
             await BinaryMessageSerializer.DeserializeMessageAsync(TestMessages.SmallBinaryResponseMessageBytes)
                 .ConfigureAwait(false);
         
         [Benchmark]
-        public async Task<ResponseMessage<List<object>>> TestReadSmallResponseMessageGraphSON3() =>
+        public async Task<ResponseMessage<List<object>>?> TestReadSmallResponseMessageGraphSON3() =>
             await GraphSON3MessageSerializer.DeserializeMessageAsync(TestMessages.SmallGraphSON3ResponseMessageBytes)
                 .ConfigureAwait(false);
         
         [Benchmark]
-        public async Task<ResponseMessage<List<object>>> TestReadBigResponseMessageBinary() =>
+        public async Task<ResponseMessage<List<object>>?> TestReadBigResponseMessageBinary() =>
             await BinaryMessageSerializer.DeserializeMessageAsync(TestMessages.BigBinaryResponseMessageBytes)
                 .ConfigureAwait(false);
         
         [Benchmark]
-        public async Task<ResponseMessage<List<object>>> TestReadBigResponseMessageGraphSON3() =>
+        public async Task<ResponseMessage<List<object>>?> TestReadBigResponseMessageGraphSON3() =>
             await GraphSON3MessageSerializer.DeserializeMessageAsync(TestMessages.BigGraphSON3ResponseMessageBytes)
                 .ConfigureAwait(false);
     }
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/ConfigProvider.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/ConfigProvider.cs
index 6b84584..3250f67 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/ConfigProvider.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/ConfigProvider.cs
@@ -46,6 +46,8 @@
             if (Convert.ToBoolean(Environment.GetEnvironmentVariable("DOCKER_ENVIRONMENT")))
             {
                 config["TestServerIpAddress"] = config["TestServerIpAddressDocker"];
+                config["GremlinSocketServerIpAddress"] = config["GremlinSocketServerIpAddressDocker"];
+                config["GremlinSocketServerConfig"] = config["GremlinSocketServerConfigDocker"];
             }
 
             return config;
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/IntroTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/IntroTests.cs
index 1d45514..f360c75 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/IntroTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/IntroTests.cs
@@ -62,7 +62,7 @@
 var peopleMarkoKnows = g.V().Has("person", "name", "marko").Out("knows").ToList();
 // end::basicGremlinMarkoKnows[]
 
-            Assert.Equal("person", marko.Label);
+            Assert.Equal("person", marko!.Label);
             Assert.Equal(2, peopleMarkoKnows.Count);
         }
     }
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/ConnectionPoolTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/ConnectionPoolTests.cs
index c4f5f7c..d35c3e3 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/ConnectionPoolTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/ConnectionPoolTests.cs
@@ -34,7 +34,7 @@
     public class ConnectionPoolTests
     {
         private readonly RequestMessageProvider _requestMessageProvider = new RequestMessageProvider();
-        private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"];
+        private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"]!;
         private static readonly int TestPort = Convert.ToInt32(ConfigProvider.Configuration["TestServerPort"]);
 
         private async Task ExecuteMultipleLongRunningRequestsInParallel(IGremlinClient gremlinClient, int nrRequests,
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/DriverRemoteConnectionTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/DriverRemoteConnectionTests.cs
index 74730c4..f0461c1 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/DriverRemoteConnectionTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/DriverRemoteConnectionTests.cs
@@ -34,7 +34,7 @@
 
 public class DriverRemoteConnectionTests
 {
-    private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"];
+    private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"]!;
     private static readonly int TestPort = Convert.ToInt32(ConfigProvider.Configuration["TestServerPort"]);
         
     [Fact]
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientAuthenticationTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientAuthenticationTests.cs
index e56e282..978e5e2 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientAuthenticationTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientAuthenticationTests.cs
@@ -35,14 +35,14 @@
 {
     public class GremlinClientAuthenticationTests
     {
-        private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"];
+        private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"]!;
         private static readonly int TestPort = Convert.ToInt32(ConfigProvider.Configuration["TestSecureServerPort"]);
         private readonly RequestMessageProvider _requestMessageProvider = new RequestMessageProvider();
 
         public static bool IgnoreCertificateValidationLiveDangerouslyWheeeeeeee(
               object sender,
-              X509Certificate certificate,
-              X509Chain chain,
+              X509Certificate? certificate,
+              X509Chain? chain,
               SslPolicyErrors sslPolicyErrors)
         {
            return true;
@@ -51,7 +51,7 @@
         [Fact]
         public async Task ShouldThrowForMissingCredentials()
         {
-            ClientWebSocketOptions optionsSet = null;
+            ClientWebSocketOptions? optionsSet = null;
             var webSocketConfiguration =
                             new Action<ClientWebSocketOptions>(options =>
                             {
@@ -75,7 +75,7 @@
         [InlineData("stephen", "wrongPassword")]
         public async Task ShouldThrowForWrongCredentials(string username, string password)
         {
-            ClientWebSocketOptions optionsSet = null;
+            ClientWebSocketOptions? optionsSet = null;
             var webSocketConfiguration =
                             new Action<ClientWebSocketOptions>(options =>
                             {
@@ -98,7 +98,7 @@
         public async Task ScriptShouldBeEvaluatedAndResultReturnedForCorrectCredentials(string requestMsg,
             string expectedResponse)
         {
-            ClientWebSocketOptions optionsSet = null;
+            ClientWebSocketOptions? optionsSet = null;
             var webSocketConfiguration =
                             new Action<ClientWebSocketOptions>(options =>
                             {
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientBehaviorIntegrationTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientBehaviorIntegrationTests.cs
new file mode 100644
index 0000000..7f5b957
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientBehaviorIntegrationTests.cs
@@ -0,0 +1,132 @@
+#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.Threading.Tasks;
+using Gremlin.Net.Driver;
+using Gremlin.Net.Driver.Exceptions;
+using Gremlin.Net.Driver.Messages;
+using Gremlin.Net.IntegrationTest.Util;
+using Gremlin.Net.Structure;
+using Gremlin.Net.Structure.IO.GraphBinary;
+using Gremlin.Net.Structure.IO.GraphSON;
+using Xunit;
+
+namespace Gremlin.Net.IntegrationTest.Driver
+{
+    public class GremlinClientBehaviorIntegrationTests
+    {
+        private static readonly string TestHost = ConfigProvider.Configuration["GremlinSocketServerIpAddress"]!;
+
+        private static readonly SocketServerSettings Settings =
+            SocketServerSettings.FromYaml(ConfigProvider.Configuration["GremlinSocketServerConfig"]);
+
+        private static IMessageSerializer Serializer;
+
+        public GremlinClientBehaviorIntegrationTests()
+        {
+            switch (Settings.Serializer)
+            {
+                case "GraphSONV2":
+                    Serializer = new GraphSON2MessageSerializer();
+                    break;
+                case "GraphSONV3":
+                    Serializer = new GraphSON3MessageSerializer();
+                    break;
+                case "GraphBinaryV1":
+                default:
+                    Serializer = new GraphBinaryMessageSerializer();
+                    break;
+            }
+        }
+
+        [Fact]
+        public async Task ShouldTryCreateNewConnectionIfClosedByServer()
+        {
+            var sessionId = Guid.NewGuid().ToString();
+            var poolSettings = new ConnectionPoolSettings {PoolSize = 1};
+            
+            var gremlinServer = new GremlinServer(TestHost, Settings.Port);
+            using var gremlinClient = new GremlinClient(gremlinServer, messageSerializer: Serializer,
+                connectionPoolSettings: poolSettings, sessionId: sessionId);
+
+            Assert.Equal(1, gremlinClient.NrConnections);
+            
+            //Send close request to server, ensure server closes connection
+            await Assert.ThrowsAsync<ConnectionClosedException>(async () =>
+                await gremlinClient.SubmitWithSingleResultAsync<Vertex>(RequestMessage.Build("1")
+                    .OverrideRequestId(Settings.CloseConnectionRequestId).Create()));
+            
+            //verify that new client reconnects and new requests can be made again
+            var response2 = await gremlinClient.SubmitWithSingleResultAsync<Vertex>(RequestMessage.Build("1")
+                .OverrideRequestId(Settings.SingleVertexRequestId).Create());
+            Assert.NotNull(response2);
+            Assert.Equal(1, gremlinClient.NrConnections);
+        }
+
+        [Fact]
+        public async Task ShouldIncludeUserAgentInHandshakeRequest()
+        {
+            var gremlinServer = new GremlinServer(TestHost, Settings.Port);
+            using var gremlinClient = new GremlinClient(gremlinServer, messageSerializer: Serializer);
+
+            //verify that the server received the correct user agent during connection setup.
+            var userAgentResponse = await gremlinClient.SubmitWithSingleResultAsync<String>(RequestMessage.Build("1")
+                .OverrideRequestId(Settings.UserAgentRequestId).Create());
+            Assert.Equal(Gremlin.Net.Process.Utils.UserAgent, userAgentResponse);
+        }
+
+        [Fact]
+        public async Task ShouldNotIncludeUserAgentInHandshakeRequestIfDisabled()
+        {
+            var poolSettings = new ConnectionPoolSettings { EnableUserAgentOnConnect = false };
+
+            var gremlinServer = new GremlinServer(TestHost, Settings.Port);
+            using var gremlinClient = new GremlinClient(gremlinServer, messageSerializer: Serializer,
+                connectionPoolSettings: poolSettings);
+
+            //verify that the server did not receive any user agent.
+            var userAgentResponse = await gremlinClient.SubmitWithSingleResultAsync<String>(RequestMessage.Build("1")
+                .OverrideRequestId(Settings.UserAgentRequestId).Create());
+            Assert.Equal("", userAgentResponse);
+        }
+
+        [Fact]
+        public async Task ShouldSendPerRequestSettingsToServer()
+        {
+            var gremlinServer = new GremlinServer(TestHost, Settings.Port);
+            using var gremlinClient = new GremlinClient(gremlinServer, messageSerializer: Serializer);
+
+            //verify that new client reconnects and new requests can be made again
+            var response = await gremlinClient.SubmitWithSingleResultAsync<String>(RequestMessage.Build("1")
+                .OverrideRequestId(Settings.PerRequestSettingsRequestId)
+                .AddArgument(Tokens.ArgsEvalTimeout, 1234)
+                .AddArgument(Tokens.ArgsBatchSize, 12)
+                .AddArgument(Tokens.ArgsUserAgent, "helloWorld")
+                .Create());
+
+            var expectedResponse = $"requestId={Settings.PerRequestSettingsRequestId} evaluationTimeout=1234, batchSize=12, userAgent=helloWorld";
+            Assert.Equal(expectedResponse, response);
+        }
+    }
+}
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs
index 454f837..b7223ec 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs
@@ -38,8 +38,8 @@
 {
     public class GremlinClientTests
     {
-        private readonly RequestMessageProvider _requestMessageProvider = new RequestMessageProvider();
-        private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"];
+        private readonly RequestMessageProvider _requestMessageProvider = new();
+        private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"]!;
         private static readonly int TestPort = Convert.ToInt32(ConfigProvider.Configuration["TestServerPort"]);
 
         [Theory]
@@ -67,7 +67,7 @@
 
                 var response = await gremlinClient.SubmitWithSingleResultAsync<string>(requestMsg);
 
-                Assert.Equal(responseMsgSize, response.Length);
+                Assert.Equal(responseMsgSize, response!.Length);
             }
         }
 
@@ -246,7 +246,7 @@
         public async Task ShouldConfigureWebSocketOptionsAsSpecified()
         {
             var gremlinServer = new GremlinServer(TestHost, TestPort);
-            ClientWebSocketOptions optionsSet = null;
+            ClientWebSocketOptions? optionsSet = null;
             var expectedKeepAliveInterval = TimeSpan.FromMilliseconds(11);
             var webSocketConfiguration =
                 new Action<ClientWebSocketOptions>(options =>
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/MessagesTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/MessagesTests.cs
index 6d6ca72..5a39b7d 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/MessagesTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/MessagesTests.cs
@@ -35,8 +35,8 @@
 {
     public class MessagesTests
     {
-        private readonly RequestMessageProvider _requestMessageProvider = new RequestMessageProvider();
-        private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"];
+        private readonly RequestMessageProvider _requestMessageProvider = new();
+        private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"]!;
         private static readonly int TestPort = Convert.ToInt32(ConfigProvider.Configuration["TestServerPort"]);
 
         [Fact]
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/MockedLoggerExtensions.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/MockedLoggerExtensions.cs
index e966876..6cad68c 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/MockedLoggerExtensions.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/MockedLoggerExtensions.cs
@@ -34,14 +34,14 @@
     {
         mockedLogger.Verify(
             m => m.Log(expectedLogLevel, It.IsAny<EventId>(),
-                It.Is<It.IsAnyType>((o, _) => o.ToString().Contains(logMessagePart)), null,
-                It.IsAny<Func<It.IsAnyType, Exception, string>>()), Times.Once);
+                It.Is<It.IsAnyType>((o, _) => o.ToString()!.Contains(logMessagePart)), null,
+                It.IsAny<Func<It.IsAnyType, Exception?, string>>()), Times.Once);
     }
     
     public static void VerifyNothingWasLogged(this Mock<ILogger> mockedLogger)
     {
         mockedLogger.Verify(
             m => m.Log(It.IsAny<LogLevel>(), It.IsAny<EventId>(), It.IsAny<It.IsAnyType>(), It.IsAny<Exception>(),
-                It.IsAny<Func<It.IsAnyType, Exception, string>>()), Times.Never);
+                It.IsAny<Func<It.IsAnyType, Exception?, string>>()), Times.Never);
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/PropertyDeserializationTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/PropertyDeserializationTests.cs
new file mode 100644
index 0000000..f4f009e
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/PropertyDeserializationTests.cs
@@ -0,0 +1,289 @@
+#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 Gremlin.Net.Driver;
+using Gremlin.Net.IntegrationTest.Process.Traversal.DriverRemoteConnection;
+using Gremlin.Net.Process.Traversal;
+using Gremlin.Net.Structure;
+using Gremlin.Net.Structure.IO.GraphBinary;
+using Gremlin.Net.Structure.IO.GraphSON;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.Json;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Gremlin.Net.IntegrationTest.Driver
+{
+    public class PropertyDeserializationTests
+    {
+        private readonly RemoteConnectionFactory _connectionFactory = new();
+
+        [Theory]
+        [MemberData(nameof(Serializers))]
+        public void ShouldDeserializeVertexPropertiesForBytecode(IMessageSerializer serializer)
+        {
+            var connection = _connectionFactory.CreateRemoteConnection("gmodern", 2, serializer);
+            var g = AnonymousTraversalSource.Traversal().WithRemote(connection);
+
+            var vertex = g.V(1).Next();
+
+            VerifyVertexProperties(vertex);
+        }
+
+        [Theory]
+        [MemberData(nameof(Serializers))]
+        public void ShouldRespectMaterializePropertiesTokensForBytecode(IMessageSerializer serializer)
+        {
+            var connection = _connectionFactory.CreateRemoteConnection("gmodern", 2, serializer);
+            var g = AnonymousTraversalSource.Traversal().WithRemote(connection);
+
+            var vertex = g.With(Tokens.ArgMaterializeProperties, "tokens").V(1).Next();
+
+            VerifyEmptyProperties(vertex);
+        }
+
+        [Theory]
+        [MemberData(nameof(Serializers))]
+        public void ShouldRespectMaterializePropertiesAllForBytecode(IMessageSerializer serializer)
+        {
+            var connection = _connectionFactory.CreateRemoteConnection("gmodern", 2, serializer);
+            var g = AnonymousTraversalSource.Traversal().WithRemote(connection);
+
+            var vertex = g.With(Tokens.ArgMaterializeProperties, "all").V(1).Next();
+
+            VerifyVertexProperties(vertex);
+        }
+
+        [Theory]
+        [MemberData(nameof(Serializers))]
+        public void ShouldHandleEmptyVertexPropertiesForBytecode(IMessageSerializer serializer)
+        {
+            var connection = _connectionFactory.CreateRemoteConnection("gimmutable", 2, serializer);
+            var g = AnonymousTraversalSource.Traversal().WithRemote(connection);
+
+            var vertex = g.AddV("test").Next();
+
+            VerifyEmptyProperties(vertex);
+        }
+
+        [Theory]
+        [MemberData(nameof(Serializers))]
+        public async Task ShouldDeserializeVertexPropertiesForGremlin(IMessageSerializer serializer)
+        {
+            var client = _connectionFactory.CreateClient(serializer);
+
+            var vertex = await client.SubmitWithSingleResultAsync<Vertex>("gmodern.V(1)");
+
+            VerifyVertexProperties(vertex);
+        }
+
+        [Theory]
+        [MemberData(nameof(Serializers))]
+        public async Task ShouldHandleEmptyVertexPropertiesForGremlin(IMessageSerializer serializer)
+        {
+            var client = _connectionFactory.CreateClient(serializer);
+
+            var vertex = await client.SubmitWithSingleResultAsync<Vertex>("gimmutable.addV('test')");
+
+            VerifyEmptyProperties(vertex);
+        }
+
+        [Theory]
+        [MemberData(nameof(Serializers))]
+        public async Task ShouldRespectMaterializePropertiesAllForGremlin(IMessageSerializer serializer)
+        {
+            var client = _connectionFactory.CreateClient(serializer);
+
+            var vertex = await client.SubmitWithSingleResultAsync<Vertex>("gmodern.with('materializeProperties', 'all').V(1)");
+
+            VerifyVertexProperties(vertex);
+        }
+
+        [Theory]
+        [MemberData(nameof(Serializers))]
+        public async Task ShouldRespectMaterializePropertiesTokensForGremlin(IMessageSerializer serializer)
+        {
+            var client = _connectionFactory.CreateClient(serializer);
+
+            var vertex = await client.SubmitWithSingleResultAsync<Vertex>("gmodern.with('materializeProperties', 'tokens').V(1)");
+
+            VerifyEmptyProperties(vertex);
+        }
+
+        [Theory]
+        [MemberData(nameof(Serializers))]
+        public void ShouldDeserializeEdgePropertiesForBytecode(IMessageSerializer serializer)
+        {
+            var connection = _connectionFactory.CreateRemoteConnection("gmodern", 2, serializer);
+            var g = AnonymousTraversalSource.Traversal().WithRemote(connection);
+
+            var edge = g.E(7).Next();
+
+            VerifyEdgeProperties(edge);
+        }
+
+        [Theory]
+        [MemberData(nameof(Serializers))]
+        public void ShouldHandleEmptyEdgePropertiesForBytecode(IMessageSerializer serializer)
+        {
+            var connection = _connectionFactory.CreateRemoteConnection("gimmutable", 2, serializer);
+            var g = AnonymousTraversalSource.Traversal().WithRemote(connection);
+
+            var v1 = g.AddV("v1").Next();
+            var v2 = g.AddV("v2").Next();
+            var edge = g.AddE("test").From(v1).To(v2).Next();
+
+            VerifyEmptyProperties(edge);
+        }
+
+        [Theory]
+        [MemberData(nameof(Serializers))]
+        public async Task ShouldDeserializeEdgePropertiesForGremlin(IMessageSerializer serializer)
+        {
+            var client = _connectionFactory.CreateClient(serializer);
+
+            var edge = await client.SubmitWithSingleResultAsync<Edge>("gmodern.E(7)");
+
+            VerifyEdgeProperties(edge);
+        }
+
+        [Theory]
+        [MemberData(nameof(Serializers))]
+        public async Task ShouldHandleEmptyEdgePropertiesForGremlin(IMessageSerializer serializer)
+        {
+            var client = _connectionFactory.CreateClient(serializer);
+
+            var edge = await client.SubmitWithSingleResultAsync<Edge>(
+                "gimmutable.addV().as('v1').addV().as('v2').addE('test').from('v1').to('v2')");
+
+            VerifyEmptyProperties(edge);
+        }
+
+        [Theory]
+        [MemberData(nameof(Serializers))]
+        public void ShouldHandleMultiplePropertiesWithSameNameForVertex(IMessageSerializer serializer)
+        {
+            var connection = _connectionFactory.CreateRemoteConnection("gimmutable", 2, serializer);
+            var g = AnonymousTraversalSource.Traversal().WithRemote(connection);
+
+            var vertex = g.AddV()
+                .Property(Cardinality.List, "test", "value1")
+                .Property(Cardinality.List, "test", "value2")
+                .Property(Cardinality.List, "test", "value3")
+                .Next()!;
+
+            vertex = g.V(vertex.Id).Next();
+
+            Assert.NotNull(vertex);
+
+            var properties = vertex.Properties!;
+            Assert.Equal(3, properties.Length);
+            var propertyValues = properties.Cast<VertexProperty>().Where(p => p.Key == "test").Select(p => p.Value).ToArray();
+            Assert.Equal(3, propertyValues.Length);
+            Assert.Equal(new[] { "value1", "value2", "value3" }, propertyValues);
+        }
+
+        [Theory]
+        [MemberData(nameof(Serializers))]
+        public void ShouldDeserializeVertexVertexPropertiesForBytecode(IMessageSerializer serializer)
+        {
+            var connection = _connectionFactory.CreateRemoteConnection("gcrew", 2, serializer);
+            var g = AnonymousTraversalSource.Traversal().WithRemote(connection);
+
+            var vertex = g.V(7).Next();
+
+            VerifyVertexVertexProperties(vertex);
+        }
+
+        [Theory]
+        [MemberData(nameof(Serializers))]
+        public async Task ShouldDeserializeVertexVertexPropertiesForGremlin(IMessageSerializer serializer)
+        {
+            var client = _connectionFactory.CreateClient(serializer);
+
+            var vertex = await client.SubmitWithSingleResultAsync<Vertex>("gcrew.V(7)");
+
+            VerifyVertexVertexProperties(vertex);
+        }
+
+        private static void VerifyVertexProperties(Vertex? vertex)
+        {
+            Assert.NotNull(vertex);
+            Assert.Equal(1, vertex.Id);
+            Assert.Equal("person", vertex.Label);
+            Assert.True(2 == vertex.Properties!.Length, $"Unexpected properties count: {JsonSerializer.Serialize(vertex.Properties)}");
+
+            var age = vertex.Property("age");
+            Assert.NotNull(age);
+            Assert.Equal(29, age.Value);
+        }
+
+        private static void VerifyVertexVertexProperties(Vertex? vertex)
+        {
+            Assert.NotNull(vertex);
+            Assert.Equal(7, vertex.Id);
+            Assert.Equal("person", vertex.Label);
+            Assert.True(4 == vertex.Properties!.Length, $"Unexpected properties count: {JsonSerializer.Serialize(vertex.Properties)}");
+
+            var locations = vertex.Properties.Cast<VertexProperty>().Where(p => p.Key == "location");
+            Assert.NotNull(locations);
+            Assert.Equal(3, locations.Count());
+
+            var vertexProperty = locations.First();
+            Assert.Equal("centreville", vertexProperty.Value);
+            Assert.Equal(2, vertexProperty.Properties!.Length);
+
+            var vertexPropertyPropertyStartTime = vertexProperty.Property("startTime");
+            Assert.Equal(1990, vertexPropertyPropertyStartTime!.Value);
+
+            var vertexPropertyPropertyEndTime = vertexProperty.Property("endTime");
+            Assert.Equal(2000, vertexPropertyPropertyEndTime!.Value);
+        }
+
+        private static void VerifyEdgeProperties(Edge? edge)
+        {
+            Assert.NotNull(edge);
+            Assert.Equal(7, edge.Id);
+            Assert.Equal("knows", edge.Label);
+            Assert.True(1 == edge.Properties!.Length, $"Unexpected properties count: {JsonSerializer.Serialize(edge.Properties)}");
+
+            var weight = edge.Property("weight");
+            Assert.NotNull(weight);
+            Assert.Equal(0.5, weight.Value);
+        }
+
+        private static void VerifyEmptyProperties(Element? element)
+        {
+            Assert.NotNull(element);
+            Assert.True((element.Properties?.Length ?? 0) == 0);
+        }
+
+        public static List<object[]> Serializers => new()
+        {
+            new [] { new GraphSON2MessageSerializer() },
+            new [] { new GraphSON3MessageSerializer() },
+            new [] { new GraphBinaryMessageSerializer() }
+        };
+    }
+}
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
index 6da7935..db99a83 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
@@ -42,20 +42,20 @@
 {
     internal class CommonSteps : StepDefinition
     {
-        private GraphTraversalSource _g;
-        private string _graphName;
-        private readonly IDictionary<string, object> _parameters = new Dictionary<string, object>();
-        private ITraversal _traversal;
-        private object[] _result;
-        private Exception _error = null;
+        private GraphTraversalSource? _g;
+        private string? _graphName;
+        private readonly IDictionary<string, object?> _parameters = new Dictionary<string, object?>();
+        private ITraversal? _traversal;
+        private object?[]? _result;
+        private Exception? _error;
 
         private static readonly JsonSerializerOptions JsonDeserializingOptions =
             new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
         
         public static ScenarioData ScenarioData { get; set; } = new ScenarioData(new GraphSON3MessageSerializer());
 
-        private static readonly IDictionary<Regex, Func<string, string, object>> Parsers =
-            new Dictionary<string, Func<string, string, object>>
+        private static readonly IDictionary<Regex, Func<string, string, object?>> Parsers =
+            new Dictionary<string, Func<string, string, object?>>
             {
                 {@"vp\[(.+)\]", ToVertexProperty},
                 {@"d\[(.*)\]\.([bsilfdmn])", ToNumber},
@@ -63,10 +63,10 @@
                 {@"M\[(.+)\]", ToMerge},
                 {@"v\[(.+)\]", ToVertex},
                 {@"v\[(.+)\]\.id", (x, graphName) => ToVertex(x, graphName).Id},
-                {@"v\[(.+)\]\.sid", (x, graphName) => ToVertex(x, graphName).Id.ToString()},
+                {@"v\[(.+)\]\.sid", (x, graphName) => ToVertex(x, graphName).Id!.ToString()},
                 {@"e\[(.+)\]", ToEdge},
                 {@"e\[(.+)\].id", (x, graphName) => ToEdge(x, graphName).Id},
-                {@"e\[(.+)\].sid", (x, graphName) => ToEdge(x, graphName).Id.ToString()},
+                {@"e\[(.+)\].sid", (x, graphName) => ToEdge(x, graphName).Id!.ToString()},
                 {@"p\[(.+)\]", ToPath},
                 {@"l\[(.*)\]", ToList},
                 {@"s\[(.*)\]", ToSet},
@@ -109,14 +109,14 @@
         [Given("using the parameter (\\w+) defined as \"(.*)\"")]
         public void UsingParameter(string name, string value)
         {
-            var parsedValue = ParseValue(value.Replace("\\\"", "\""), _graphName);
+            var parsedValue = ParseValue(value.Replace("\\\"", "\""), _graphName!);
             _parameters.Add(name, parsedValue);
         }
 
         [Given("using the parameter (\\w+) of P.(\\w+)\\(\"(.*)\"\\)")]
         public void UsingParameterP(string name, string pval, string value)
         {
-            var parsedValue = ParseValue(value.Replace("\\\"", "\""), _graphName);
+            var parsedValue = ParseValue(value.Replace("\\\"", "\""), _graphName!);
             _parameters.Add(name, new P(pval, parsedValue));
         }
 
@@ -128,20 +128,20 @@
                 throw new InvalidOperationException("g should be a traversal source");
             }
 
-            if (ScenarioData.CurrentFeature.Tags.Select(t => t.Name).ToList().Contains("@GraphComputerOnly"))
+            if (ScenarioData.CurrentFeature!.Tags.Any(t => t.Name == "@GraphComputerOnly"))
             {
                 _g = _g.WithComputer();
             }
 
             _traversal =
-                Gremlin.UseTraversal(ScenarioData.CurrentScenario.Name, _g, _parameters);
+                Gremlin.UseTraversal(ScenarioData.CurrentScenario!.Name, _g, _parameters);
         }
 
         [Given("the graph initializer of")]
         public void InitTraversal(string traversalText)
         {
             var traversal =
-                Gremlin.UseTraversal(ScenarioData.CurrentScenario.Name, _g, _parameters);
+                Gremlin.UseTraversal(ScenarioData.CurrentScenario!.Name, _g, _parameters);
             traversal.Iterate();
             
             // We may have modified the so-called `empty` graph
@@ -227,13 +227,13 @@
 
             switch (comparison) {
                 case "containing":
-                    Assert.Equal(true, _error.Message.Contains(expectedMessage));
+                    Assert.Contains(expectedMessage, _error.Message);
                     break;
                 case "starting":
-                    Assert.Equal(true, _error.Message.StartsWith(expectedMessage));
+                    Assert.StartsWith(expectedMessage, _error.Message);
                     break;
                 case "ending":
-                    Assert.Equal(true, _error.Message.EndsWith(expectedMessage));
+                    Assert.EndsWith(expectedMessage, _error.Message);
                     break;
                 default:
                     throw new NotSupportedException(
@@ -245,15 +245,15 @@
         }
 
         [Then("the result should be (\\w+)")]
-        public void AssertResult(string characterizedAs, DataTable table = null)
+        public void AssertResult(string characterizedAs, DataTable? table = null)
         {
-            assertThatNoErrorWasThrown();
+            AssertThatNoErrorWasThrown();
 
             var ordered = characterizedAs == "ordered";
             switch (characterizedAs)
             {
                 case "empty":
-                    Assert.Empty(_result);
+                    Assert.Empty(_result!);
                     return;
                 case "ordered":
                 case "unordered":
@@ -261,16 +261,16 @@
                     Assert.NotNull(table);
                     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));
+                    var expected = rows.Skip(1).Select(x => ParseValue(x.Cells.First().Value, _graphName!));
 
                     if (ordered)
                     {
-                        Assert.Equal(expected, _result);
+                        Assert.Equal(expected, _result!);
                     }
                     else
                     {
                         var expectedArray = expected.ToArray();
-                        foreach (var resultItem in _result)
+                        foreach (var resultItem in _result!)
                         {
                             if (resultItem is Dictionary<object, object> resultItemDict)
                             {
@@ -285,7 +285,7 @@
                                 Assert.True(expectedArrayContainsResultDictionary);
                             }
                             else if (resultItem is double resultItemDouble &&
-                                     expectedArray.Select(e => e.GetType()).Any(t => t == typeof(decimal)))
+                                     expectedArray.Select(e => e!.GetType()).Any(t => t == typeof(decimal)))
                             {
                                 // Java seems to use BigDecimal by default sometimes where .NET uses double, but we only
                                 // care for the value not its type here. So we just convert these to decimal (equivalent
@@ -311,15 +311,15 @@
         [Then("the result should have a count of (\\d+)")]
         public void AssertCount(int count)
         {
-            assertThatNoErrorWasThrown();
+            AssertThatNoErrorWasThrown();
 
-            Assert.Equal(count, _result.Length);
+            Assert.Equal(count, _result!.Length);
         }
 
         [Then("the graph should return (\\d+) for count of (.+)")]
         public void AssertTraversalCount(int expectedCount, string traversalText)
         {
-            assertThatNoErrorWasThrown();
+            AssertThatNoErrorWasThrown();
 
             if (traversalText.StartsWith("\""))
             {
@@ -327,7 +327,7 @@
             }
             
             var traversal =
-                Gremlin.UseTraversal(ScenarioData.CurrentScenario.Name, _g, _parameters);
+                Gremlin.UseTraversal(ScenarioData.CurrentScenario!.Name, _g, _parameters);
             
             var count = 0;
             while (traversal.MoveNext())
@@ -343,7 +343,7 @@
             
         }
 
-        private void assertThatNoErrorWasThrown()
+        private void AssertThatNoErrorWasThrown()
         {
             if (_error != null) throw _error;
         }
@@ -351,7 +351,7 @@
         private static object ToMap(string stringMap, string graphName)
         {
             var jsonMap = JsonSerializer.Deserialize<JsonElement>(stringMap, JsonDeserializingOptions);
-            return ParseMapValue(jsonMap, graphName);
+            return ParseMapValue(jsonMap, graphName)!;
         }
 
         private static object ToLambda(string stringLambda, string graphName)
@@ -380,13 +380,13 @@
                 stringNumber.Substring(0, stringNumber.Length - 1));
         }
 
-        private static object ParseMapValue(JsonElement value, string graphName)
+        private static object? ParseMapValue(JsonElement value, string graphName)
         {
             switch (value.ValueKind)
             {
                 case JsonValueKind.Object:
                 {
-                    return value.EnumerateObject().ToDictionary(property => ParseValue(property.Name, graphName),
+                    return value.EnumerateObject().ToDictionary(property => ParseValue(property.Name, graphName)!,
                         property => ParseMapValue(property.Value, graphName));
                 }
                 case JsonValueKind.Array:
@@ -408,7 +408,7 @@
                     throw new ArgumentOutOfRangeException(nameof(value), value, "Not a supported number type");
                 }
                 case JsonValueKind.String:
-                    return ParseValue(value.GetString(), graphName);
+                    return ParseValue(value.GetString()!, graphName);
                 case JsonValueKind.True:
                     return true;
                 case JsonValueKind.False:
@@ -421,16 +421,16 @@
             }
         }
 
-        private static ISet<object> ToSet(string stringSet, string graphName)
+        private static ISet<object?> ToSet(string stringSet, string graphName)
         {
-            return new HashSet<object>(ToList(stringSet, graphName));
+            return new HashSet<object?>(ToList(stringSet, graphName));
         }
 
-        private static IList<object> ToList(string stringList, string graphName)
+        private static IList<object?> ToList(string stringList, string graphName)
         {
             if (stringList == "")
             {
-                return new List<object>(0);
+                return new List<object?>(0);
             }
             return stringList.Split(',').Select(x => ParseValue(x, graphName)).ToList();
         }
@@ -459,13 +459,14 @@
 
         private static Path ToPath(string value, string graphName)
         {
-            return new Path(new List<ISet<string>>(0), value.Split(',').Select(x => ParseValue(x, graphName)).ToList());
+            return new Path(new List<ISet<string>>(0),
+                value.Split(',').Select(x => ParseValue(x, graphName)).ToList());
         }
 
-        private static object ParseValue(string stringValue, string graphName)
+        private static object? ParseValue(string stringValue, string graphName)
         {
-            Func<string, string, object> parser = null;
-            string extractedValue = null;
+            Func<string, string, object?>? parser = null;
+            string? extractedValue = null;
             foreach (var kv in Parsers)
             {
                 var match = kv.Key.Match(stringValue);
@@ -480,7 +481,7 @@
                     break;
                 }
             }
-            return parser != null ? parser(extractedValue, graphName) : stringValue;
+            return parser != null ? parser(extractedValue!, graphName) : stringValue;
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
index f794184..df63253 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
@@ -114,7 +114,7 @@
                     }
 
                     StepBlock? currentStep = null;
-                    StepDefinition stepDefinition = null;
+                    StepDefinition? stepDefinition = null;
                     foreach (var step in scenario.Steps)
                     {
                         var previousStep = currentStep;
@@ -238,13 +238,13 @@
             }
         }
 
-        private Exception ExecuteStep(StepDefinition instance, StepBlock stepBlock, Step step)
+        private Exception? ExecuteStep(StepDefinition instance, StepBlock stepBlock, Step step)
         {
             var attribute = Attributes[stepBlock];
             var methodAndParameters = instance.GetType().GetMethods()
                 .Select(m =>
                 {
-                    var attr = (BddAttribute) m.GetCustomAttribute(attribute);
+                    var attr = (BddAttribute?) m.GetCustomAttribute(attribute);
                     
                     if (attr == null)
                     {
@@ -255,7 +255,7 @@
                     {
                         return null;
                     }
-                    var parameters = new List<object>();
+                    var parameters = new List<object?>();
                     for (var i = 1; i < match.Groups.Count; i++)
                     {
                         parameters.Add(match.Groups[i].Value);
@@ -358,7 +358,7 @@
             {
                 throw new InvalidOperationException($"No step definition class matches Given '{stepText}'");
             }
-            return (StepDefinition) Activator.CreateInstance(type);
+            return (StepDefinition) Activator.CreateInstance(type)!;
         }
 
         private ICollection<Type> GetStepDefinitionTypes()
@@ -391,9 +391,9 @@
         {
             var codeBaseUrl = new Uri(GetType().GetTypeInfo().Assembly.Location);
             var codeBasePath = Uri.UnescapeDataString(codeBaseUrl.AbsolutePath);
-            DirectoryInfo rootDir = null;
-            for (var dir = Directory.GetParent(Path.GetDirectoryName(codeBasePath));
-                dir.Parent != null;
+            DirectoryInfo? rootDir = null;
+            for (var dir = Directory.GetParent(Path.GetDirectoryName(codeBasePath)!);
+                dir!.Parent != null;
                 dir = dir.Parent)
             {
                 if (dir.Name == "gremlin-dotnet" && dir.GetFiles("pom.xml").Length == 1)
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 6580b19..290b2fe 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -27,6 +27,7 @@
 //* Do NOT edit this file directly - generated by build/generate.groovy
 //********************************************************************************
 
+#nullable disable
 
 using System;
 using System.Collections.Generic;
@@ -504,6 +505,12 @@
                {"g_E_sampleX1X_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E().Sample(1).Count()}}, 
                {"g_V_sampleX1X_byXageX_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Sample(1).By("age").Count()}}, 
                {"g_V_order_byXnoX_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Order().By("no").Count()}}, 
+               {"g_V_EX11X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().E(p["eid11"])}}, 
+               {"g_EX11X_E", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["eid11"]).E()}}, 
+               {"g_V_EXnullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().E(null)}}, 
+               {"g_V_EXlistXnullXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().E(p["xx1"])}}, 
+               {"g_injectX1X_EX11_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(1).E(p["eid11"],null)}}, 
+               {"g_injectX1X_coalesceXEX_hasLabelXtestsX_addEXtestsX_from_V_hasXnameX_XjoshXX_toXV_hasXnameX_XvadasXXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV("person").Property("name","josh").AddV("person").Property("name","vadas"), (g,p) =>g.Inject(1).Coalesce<object>(__.E().HasLabel("tests"),__.AddE("tests").From(__.V().Has("name","josh")).To(__.V().Has("name","vadas"))), (g,p) =>g.E().HasLabel("tests")}}, 
                {"g_VX1X_properties_element", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V((Vertex) p["v2"]).Properties<object>().Element().Limit<object>(1)}}, 
                {"g_V_properties_element", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Properties<object>().Element()}}, 
                {"g_V_propertiesXageX_element", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Properties<object>("age").Element()}}, 
@@ -1169,3 +1176,5 @@
     }
 }
 
+#nullable restore
+
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/IgnoreException.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/IgnoreException.cs
index 035cf56..04d5a06 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/IgnoreException.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/IgnoreException.cs
@@ -37,7 +37,7 @@
 
         private static string GetMessage(IgnoreReason reason)
         {
-            string reasonSuffix = null;
+            string? reasonSuffix = null;
             switch (reason)
             {
                 case IgnoreReason.NoReason:
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs
index b7660c3..1c8be14 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs
@@ -52,8 +52,8 @@
         
         private readonly RemoteConnectionFactory _connectionFactory;
 
-        public Scenario CurrentScenario;
-        public Feature CurrentFeature;
+        public Scenario? CurrentScenario;
+        public Feature? CurrentFeature;
 
         public ScenarioDataPerGraph GetByGraphName(string name)
         {
@@ -109,7 +109,7 @@
             // 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()
+                return g.V().Group<string, object>().By("name").By(__.Tail<Vertex>()).Next()!
                     .ToDictionary(kv => kv.Key, kv => (Vertex) kv.Value);
             }
             else
@@ -128,7 +128,7 @@
                 return g.E().Group<string, Edge>()
                     .By(lambda)
                     .By(__.Tail<object>())
-                    .Next();
+                    .Next()!;
             }
             catch (ResponseException)
             {
@@ -191,7 +191,7 @@
                 return g.V().Properties<VertexProperty>().Group<string, VertexProperty>()
                     .By(lambda)
                     .By(__.Tail<object>())
-                    .Next();
+                    .Next()!;
             }
             catch (ResponseException)
             {
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gremlin.Net.IntegrationTest.csproj b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gremlin.Net.IntegrationTest.csproj
index 15e13d6..8c5ba7e 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gremlin.Net.IntegrationTest.csproj
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gremlin.Net.IntegrationTest.csproj
@@ -1,6 +1,10 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
+    <Nullable>enable</Nullable>
+    <AssemblyOriginatorKeyFile>../../build/tinkerpop.snk</AssemblyOriginatorKeyFile>
+    <SignAssembly>true</SignAssembly>
+    <PublicSign Condition="'$(OS)' != 'Windows_NT'">true</PublicSign>
   </PropertyGroup>
   <ItemGroup>
     <None Update="appsettings.json">
@@ -19,6 +23,7 @@
     <PackageReference Include="xunit" Version="2.4.2" />
     <PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
     <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
+    <PackageReference Include="YamlDotNet" Version="12.2.0" />
   </ItemGroup>
   <ItemGroup>
     <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Remote/RemoteStrategyTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Remote/RemoteStrategyTests.cs
index f01116d..33b4ab4 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Remote/RemoteStrategyTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Remote/RemoteStrategyTests.cs
@@ -34,7 +34,7 @@
 {
     public class RemoteStrategyTests
     {
-        private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"];
+        private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"]!;
         private static readonly int TestPort = Convert.ToInt32(ConfigProvider.Configuration["TestServerPort"]);
 
         [Fact]
@@ -93,5 +93,7 @@
             TraversalStrategies.Add(traversalStrategy);
             Bytecode = bytecode;
         }
+
+        public override Bytecode Bytecode { get; }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/BytecodeGeneration/BytecodeGenerationTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/BytecodeGeneration/BytecodeGenerationTests.cs
index adac06b..cea8e23 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/BytecodeGeneration/BytecodeGenerationTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/BytecodeGeneration/BytecodeGenerationTests.cs
@@ -110,7 +110,7 @@
         [Fact]
         public void AnonymousTraversal_OutXnullX()
         {
-            Assert.Throws<ArgumentNullException>(() => __.Out(null));
+            Assert.Throws<ArgumentNullException>(() => __.Out(null!));
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/BytecodeGeneration/StrategiesTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/BytecodeGeneration/StrategiesTests.cs
index 3a76a84..24c5e63 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/BytecodeGeneration/StrategiesTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/BytecodeGeneration/StrategiesTests.cs
@@ -90,7 +90,7 @@
             Assert.Equal("withStrategies", bytecode.SourceInstructions[0].OperatorName);
             Assert.Equal(new MatchAlgorithmStrategy(), bytecode.SourceInstructions[0].Arguments[0]);
             Assert.Contains("greedy",
-                ((MatchAlgorithmStrategy) bytecode.SourceInstructions[0].Arguments[0]).Configuration.Values);
+                ((MatchAlgorithmStrategy) bytecode.SourceInstructions[0].Arguments[0]!).Configuration.Values);
         }
 
         [Fact]
@@ -118,8 +118,9 @@
             Assert.Single(bytecode.SourceInstructions[0].Arguments);
             Assert.Equal("withStrategies", bytecode.SourceInstructions[0].OperatorName);
             Assert.Equal(new ReadOnlyStrategy(), bytecode.SourceInstructions[0].Arguments[0]);
-            Assert.Equal("ReadOnlyStrategy", bytecode.SourceInstructions[0].Arguments[0].ToString());
-            Assert.Equal(new ReadOnlyStrategy().GetHashCode(), bytecode.SourceInstructions[0].Arguments[0].GetHashCode());
+            Assert.Equal("ReadOnlyStrategy", bytecode.SourceInstructions[0].Arguments[0]!.ToString());
+            Assert.Equal(new ReadOnlyStrategy().GetHashCode(),
+                bytecode.SourceInstructions[0].Arguments[0]!.GetHashCode());
             Assert.Equal(0, g.TraversalStrategies.Count);
         }
 
@@ -150,9 +151,9 @@
             Assert.Single(bytecode.SourceInstructions[0].Arguments);
             Assert.Equal("withStrategies", bytecode.SourceInstructions[0].OperatorName);
             Assert.Equal(new SubgraphStrategy(), bytecode.SourceInstructions[0].Arguments[0]);
-            SubgraphStrategy strategy = bytecode.SourceInstructions[0].Arguments[0];
-            Assert.Equal(typeof(GraphTraversal<object, object>), strategy.Configuration["vertices"].GetType());
-            ITraversal traversal = strategy.Configuration["vertices"];
+            SubgraphStrategy strategy = bytecode.SourceInstructions[0].Arguments[0]!;
+            Assert.Equal(typeof(GraphTraversal<object, object>), strategy.Configuration["vertices"]!.GetType());
+            ITraversal traversal = strategy.Configuration["vertices"]!;
             Assert.Equal("has", traversal.Bytecode.StepInstructions[0].OperatorName);
             Assert.Equal(new List<string> {"name", "marko"}, traversal.Bytecode.StepInstructions[0].Arguments);
             Assert.Equal(false, strategy.Configuration["checkAdjacentVertices"]);
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 262ffea..73cbff3 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
@@ -84,7 +84,7 @@
             var vertex = g.V(1).Next();
 
             Assert.Equal(new Vertex(1), vertex);
-            Assert.Equal(1, vertex.Id);
+            Assert.Equal(1, vertex!.Id);
         }
 
         [Fact]
@@ -143,7 +143,7 @@
             var shortestPath =
                 g.V(5).Repeat(__.Both().SimplePath()).Until(__.HasId(6)).Limit<Vertex>(1).Path().Next();
 
-            Assert.Equal(4, shortestPath.Count);
+            Assert.Equal(4, shortestPath!.Count);
             Assert.Equal(new Vertex(6), shortestPath[3]);
         }
 
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/RemoteConnectionFactory.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/RemoteConnectionFactory.cs
index 8fe6c2e..f24b1c4 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/RemoteConnectionFactory.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Process/Traversal/DriverRemoteConnection/RemoteConnectionFactory.cs
@@ -32,36 +32,45 @@
 {
     internal class RemoteConnectionFactory : IDisposable
     {
-        private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"];
+        private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"]!;
         private static readonly int TestPort = Convert.ToInt32(ConfigProvider.Configuration["TestServerPort"]);
 
-        private readonly IList<DriverRemoteConnectionImpl> _connections = new List<DriverRemoteConnectionImpl>();
+        private readonly IList<IDisposable> _cleanUp = new List<IDisposable>();
         private readonly IMessageSerializer _messageSerializer;
 
-        public RemoteConnectionFactory(IMessageSerializer messageSerializer = null)
+        public RemoteConnectionFactory(IMessageSerializer? messageSerializer = null)
         {
             _messageSerializer = messageSerializer ?? new GraphSON3MessageSerializer();
         }
-        
+
         public IRemoteConnection CreateRemoteConnection(int connectionPoolSize = 2)
         {
             // gmodern is the standard test traversalsource that the main body of test uses
             return CreateRemoteConnection("gmodern", connectionPoolSize);
         }
 
-        public IRemoteConnection CreateRemoteConnection(string traversalSource, int connectionPoolSize = 2)
+        public IRemoteConnection CreateRemoteConnection(string traversalSource,
+            int connectionPoolSize = 2,
+            IMessageSerializer? messageSerializer = null)
         {
-            var c = new DriverRemoteConnectionImpl(
-                new GremlinClient(new GremlinServer(TestHost, TestPort), _messageSerializer,
-                    connectionPoolSettings: new ConnectionPoolSettings { PoolSize = connectionPoolSize }),
-                traversalSource);
-            _connections.Add(c);
+            var c = new DriverRemoteConnectionImpl(CreateClient(messageSerializer, connectionPoolSize), traversalSource);
+            _cleanUp.Add(c);
+            return c;
+        }
+
+        public IGremlinClient CreateClient(IMessageSerializer? messageSerializer = null, int connectionPoolSize = 2)
+        {
+            var c = new GremlinClient(new GremlinServer(TestHost, TestPort),
+                    messageSerializer ?? _messageSerializer,
+                    connectionPoolSettings: new() { PoolSize = connectionPoolSize });
+
+            _cleanUp.Add(c);
             return c;
         }
 
         public void Dispose()
         {
-            foreach (var connection in _connections)
+            foreach (var connection in _cleanUp)
             {
                 connection.Dispose();
             }
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Util/SocketServerSettings.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Util/SocketServerSettings.cs
new file mode 100644
index 0000000..2ae0e22
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Util/SocketServerSettings.cs
@@ -0,0 +1,94 @@
+#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.IO;
+using YamlDotNet.Serialization;
+
+namespace Gremlin.Net.IntegrationTest.Util;
+
+public class SocketServerSettings
+{
+    [YamlMember(Alias = "PORT", ApplyNamingConventions = false)]
+    public int Port { get; set; }
+
+    /**
+     * Configures which serializer will be used. Ex: "GraphBinaryV1" or "GraphSONV2"
+     */
+    [YamlMember(Alias = "SERIALIZER", ApplyNamingConventions = false)]
+    public String Serializer { get; set; }
+
+    /**
+     * If a request with this ID comes to the server, the server responds back with a single vertex picked from Modern
+     * graph.
+     */
+    [YamlMember(Alias = "SINGLE_VERTEX_REQUEST_ID", ApplyNamingConventions = false)]
+    public Guid SingleVertexRequestId { get; set; }
+
+    /**
+     * If a request with this ID comes to the server, the server responds back with a single vertex picked from Modern
+     * graph. After a 2 second delay, server sends a Close WebSocket frame on the same connection.
+     */
+    [YamlMember(Alias = "SINGLE_VERTEX_DELAYED_CLOSE_CONNECTION_REQUEST_ID", ApplyNamingConventions = false)]
+    public Guid SingleVertexDelayedCloseConnectionRequestId { get; set; }
+
+    /**
+     * Server waits for 1 second, then responds with a 500 error status code
+     */
+    [YamlMember(Alias = "FAILED_AFTER_DELAY_REQUEST_ID", ApplyNamingConventions = false)]
+    public Guid FailedAfterDelayRequestId { get; set; }
+
+    /**
+     * Server waits for 1 second then responds with a close web socket frame
+     */
+    [YamlMember(Alias = "CLOSE_CONNECTION_REQUEST_ID", ApplyNamingConventions = false)]
+    public Guid CloseConnectionRequestId { get; set; }
+
+    /**
+     * Same as CLOSE_CONNECTION_REQUEST_ID
+     */
+    [YamlMember(Alias = "CLOSE_CONNECTION_REQUEST_ID_2", ApplyNamingConventions = false)]
+    public Guid CloseConnectionRequestId2 { get; set; }
+
+    /**
+     * If a request with this ID comes to the server, the server responds with the user agent (if any) that was captured
+     * during the web socket handshake.
+     */
+    [YamlMember(Alias = "USER_AGENT_REQUEST_ID", ApplyNamingConventions = false)]
+    public Guid UserAgentRequestId { get; set; }
+    
+    /**
+     * If a request with this ID comes to the server, the server responds with a string containing all overridden
+     * per request settings from the request message. String will be of the form
+     * "requestId=19436d9e-f8fc-4b67-8a76-deec60918424 evaluationTimeout=1234, batchSize=12, userAgent=testUserAgent"
+     */
+    [YamlMember(Alias = "PER_REQUEST_SETTINGS_REQUEST_ID", ApplyNamingConventions = false)]
+    public Guid PerRequestSettingsRequestId { get; set; }
+    
+    public static SocketServerSettings FromYaml(String path)
+    {
+        var deserializer = new YamlDotNet.Serialization.DeserializerBuilder().IgnoreUnmatchedProperties().Build();
+
+        return deserializer.Deserialize<SocketServerSettings>(File.ReadAllText(path));
+    }
+}
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/appsettings.json b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/appsettings.json
index 5d095ff..b62dbe8 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/appsettings.json
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/appsettings.json
@@ -2,5 +2,9 @@
   "TestServerIpAddress": "localhost",
   "TestServerIpAddressDocker": "gremlin-server-test-dotnet",
   "TestServerPort": 45940,
-  "TestSecureServerPort": 45941
+  "TestSecureServerPort": 45941,
+  "GremlinSocketServerIpAddress": "localhost",
+  "GremlinSocketServerIpAddressDocker": "gremlin-socket-server",
+  "GremlinSocketServerConfig": "../../../../../../gremlin-tools/gremlin-socket-server/conf/test-ws-gremlin.yaml",
+  "GremlinSocketServerConfigDocker": "../../../../../gremlin-socket-server/conf/test-ws-gremlin.yaml"
 }
diff --git a/gremlin-dotnet/test/Gremlin.Net.Template.IntegrationTest/Gremlin.Net.Template.IntegrationTest.csproj b/gremlin-dotnet/test/Gremlin.Net.Template.IntegrationTest/Gremlin.Net.Template.IntegrationTest.csproj
index dd9a0d5..ee4039b 100644
--- a/gremlin-dotnet/test/Gremlin.Net.Template.IntegrationTest/Gremlin.Net.Template.IntegrationTest.csproj
+++ b/gremlin-dotnet/test/Gremlin.Net.Template.IntegrationTest/Gremlin.Net.Template.IntegrationTest.csproj
@@ -2,6 +2,7 @@
 
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
 
   <ItemGroup>
diff --git a/gremlin-dotnet/test/Gremlin.Net.Template.IntegrationTest/ServiceTests.cs b/gremlin-dotnet/test/Gremlin.Net.Template.IntegrationTest/ServiceTests.cs
index 1faa0b8..faef08e 100644
--- a/gremlin-dotnet/test/Gremlin.Net.Template.IntegrationTest/ServiceTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.Template.IntegrationTest/ServiceTests.cs
@@ -34,7 +34,7 @@
 {
     public class ServiceTests
     {
-        private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"];
+        private static readonly string TestHost = ConfigProvider.Configuration["TestServerIpAddress"]!;
         private static readonly int TestPort = Convert.ToInt32(ConfigProvider.Configuration["TestServerPort"]);
         private const string TestTraversalSource = "gmodern";
 
@@ -48,7 +48,7 @@
             
                 var creators = service.FindCreatorsOfSoftware("lop");
 
-                Assert.Equal(new List<string> {"marko", "josh", "peter"}, creators);
+                Assert.Equal(new List<string?> {"marko", "josh", "peter"}, creators);
             }
         }
 
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/ConnectionPoolTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/ConnectionPoolTests.cs
index 0fbc02a..e5711b0 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/ConnectionPoolTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/ConnectionPoolTests.cs
@@ -27,6 +27,7 @@
 using System.Threading.Tasks;
 using Gremlin.Net.Driver;
 using Gremlin.Net.Driver.Exceptions;
+using Gremlin.Net.Driver.Messages;
 using Microsoft.Extensions.Logging.Abstractions;
 using Moq;
 using Xunit;
@@ -188,7 +189,8 @@
             fakedConnection.Setup(f => f.IsOpen).Returns(false);
             mockedConnectionFactory.Setup(m => m.CreateConnection()).Returns(OpenConnection);
 
-            await returnedConnection.SubmitAsync<bool>(null, CancellationToken.None);
+            await returnedConnection.SubmitAsync<bool>(RequestMessage.Build(string.Empty).Create(),
+                CancellationToken.None);
             returnedConnection.Dispose();
 
             Assert.Equal(1, pool.NrConnections);
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/ConnectionTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/ConnectionTests.cs
index 44c7105..26e483a 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/ConnectionTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/ConnectionTests.cs
@@ -294,10 +294,8 @@
             var fakeMessageSerializer = new Mock<IMessageSerializer>();
             var receivedBytes = new byte[] { 1, 2, 3 };
             var messageToCancel = RequestMessage.Build(string.Empty).Create();
-            var receivedMessage = new ResponseMessage<List<object>>
-            {
-                RequestId = messageToCancel.RequestId, Status = new ResponseStatus { Code = ResponseStatusCode.Success }
-            };
+            var receivedMessage = new ResponseMessage<List<object>>(messageToCancel.RequestId,
+                new ResponseStatus(ResponseStatusCode.Success), new ResponseResult<List<object>>(null));
             fakeMessageSerializer.Setup(f => f.DeserializeMessageAsync(receivedBytes, It.IsAny<CancellationToken>()))
                 .ReturnsAsync(receivedMessage);
             var fakeWebSocketConnection = new Mock<IWebSocketConnection>();
@@ -316,14 +314,14 @@
         }
 
         private static Connection GetConnection(IMock<IClientWebSocket> mockedClientWebSocket,
-            IMessageSerializer messageSerializer = null, Uri uri = null)
+            IMessageSerializer? messageSerializer = null, Uri? uri = null)
         {
             return GetConnection(new WebSocketConnection(mockedClientWebSocket.Object, new WebSocketSettings()),
                 messageSerializer, uri);
         }
         
         private static Connection GetConnection(IWebSocketConnection webSocketConnection,
-            IMessageSerializer messageSerializer = null, Uri uri = null)
+            IMessageSerializer? messageSerializer = null, Uri? uri = null)
         {
             uri ??= new Uri("wss://localhost:8182");
             messageSerializer ??= new GraphBinaryMessageSerializer();
@@ -336,9 +334,10 @@
                 sessionId: null);
         }
 
-        private static async Task AssertExpectedConnectionClosedException(WebSocketCloseStatus? expectedCloseStatus, string expectedCloseDescription, Func<Task> func)
+        private static async Task AssertExpectedConnectionClosedException(WebSocketCloseStatus? expectedCloseStatus,
+            string? expectedCloseDescription, Func<Task> func)
         {
-            ConnectionClosedException exception = await Assert.ThrowsAsync<ConnectionClosedException>(func);
+            var exception = await Assert.ThrowsAsync<ConnectionClosedException>(func);
             Assert.Equal(expectedCloseStatus, exception.Status);
             Assert.Equal(expectedCloseDescription, exception.Description);
         }
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/DriverRemoteConnectionTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/DriverRemoteConnectionTests.cs
index 7ed9c96..8780cf9 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/DriverRemoteConnectionTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/DriverRemoteConnectionTests.cs
@@ -45,7 +45,7 @@
         [Fact]
         public void ShouldThrowWhenGivenNullAsGremlinClient()
         {
-            Assert.Throws<ArgumentNullException>(() => new DriverRemoteConnection(null));
+            Assert.Throws<ArgumentNullException>(() => new DriverRemoteConnection(null!));
         }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/GraphSONMessageSerializerTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/GraphSONMessageSerializerTests.cs
index 6b7951f..6aae175 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/GraphSONMessageSerializerTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/GraphSONMessageSerializerTests.cs
@@ -36,7 +36,7 @@
         {
             var sut = CreateMessageSerializer();
 
-            await Assert.ThrowsAsync<ArgumentNullException>(()=> sut.DeserializeMessageAsync(null));
+            await Assert.ThrowsAsync<ArgumentNullException>(()=> sut.DeserializeMessageAsync(null!));
         }
 
         [Fact]
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 e14d7ee..1b6a742 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Gremlin.Net.UnitTest.csproj
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Gremlin.Net.UnitTest.csproj
@@ -2,6 +2,7 @@
 
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
+    <Nullable>enable</Nullable>
     <AssemblyOriginatorKeyFile>../../build/tinkerpop.snk</AssemblyOriginatorKeyFile>
     <SignAssembly>true</SignAssembly>
     <PublicSign Condition="'$(OS)' != 'Windows_NT'">true</PublicSign>
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/BytecodeTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/BytecodeTests.cs
index d9ab4a7..1f91af6 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/BytecodeTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/BytecodeTests.cs
@@ -62,7 +62,7 @@
             bytecode.AddStep("someStep", new Dictionary<string, object> {{"someKey", b.Of("valVariable", "valValue")}});
 
             var arg = bytecode.StepInstructions[0].Arguments[0] as IDictionary;
-            Assert.Equal(new Binding("valVariable", "valValue"), arg["someKey"]);
+            Assert.Equal(new Binding("valVariable", "valValue"), arg!["someKey"]);
         }
 
         [Fact]
@@ -74,7 +74,7 @@
             bytecode.AddStep("someStep", new Dictionary<string, object> {{b.Of("keyVariable", "keyValue"), 1234}});
 
             var arg = bytecode.StepInstructions[0].Arguments[0];
-            var binding = ((Dictionary<object, object>) arg).Keys.First() as Binding;
+            var binding = ((Dictionary<object, object>) arg!).Keys.First() as Binding;
             Assert.Equal(new Binding("keyVariable", "keyValue"), binding);
         }
 
@@ -87,7 +87,7 @@
             bytecode.AddStep("someStep", new List<string> {"test", b.Of("listVariable", "listValue")});
 
             var arg = bytecode.StepInstructions[0].Arguments[0] as IList;
-            Assert.Equal(new Binding("listVariable", "listValue"), arg[1]);
+            Assert.Equal(new Binding("listVariable", "listValue"), arg![1]);
         }
 
         [Fact]
@@ -99,7 +99,7 @@
             bytecode.AddStep("someStep", new HashSet<string> { "test", b.Of("setVariable", "setValue") });
 
             var arg = bytecode.StepInstructions[0].Arguments[0] as ISet<object>;
-            Assert.Equal(new Binding("setVariable", "setValue"), arg.ToList()[1]);
+            Assert.Equal(new Binding("setVariable", "setValue"), arg!.ToList()[1]);
         }
 
         [Fact]
@@ -133,7 +133,7 @@
             bytecode.AddSource("someSource", new Dictionary<string, object> { { "someKey", b.Of("valVariable", "valValue") } });
 
             var arg = bytecode.SourceInstructions[0].Arguments[0] as IDictionary;
-            Assert.Equal(new Binding("valVariable", "valValue"), arg["someKey"]);
+            Assert.Equal(new Binding("valVariable", "valValue"), arg!["someKey"]);
         }
 
         [Fact]
@@ -145,7 +145,7 @@
             bytecode.AddSource("someSource", new Dictionary<string, object> { { b.Of("keyVariable", "keyValue"), 1234 } });
 
             var arg = bytecode.SourceInstructions[0].Arguments[0];
-            var binding = ((Dictionary<object, object>)arg).Keys.First() as Binding;
+            var binding = ((Dictionary<object, object>)arg!).Keys.First() as Binding;
             Assert.Equal(new Binding("keyVariable", "keyValue"), binding);
         }
 
@@ -158,7 +158,7 @@
             bytecode.AddSource("someSource", new List<string> { "test", b.Of("listVariable", "listValue") });
 
             var arg = bytecode.SourceInstructions[0].Arguments[0] as IList;
-            Assert.Equal(new Binding("listVariable", "listValue"), arg[1]);
+            Assert.Equal(new Binding("listVariable", "listValue"), arg![1]);
         }
 
         [Fact]
@@ -170,7 +170,7 @@
             bytecode.AddSource("someSource", new HashSet<string> { "test", b.Of("setVariable", "setValue") });
 
             var arg = bytecode.SourceInstructions[0].Arguments[0] as ISet<object>;
-            Assert.Equal(new Binding("setVariable", "setValue"), arg.ToList()[1]);
+            Assert.Equal(new Binding("setVariable", "setValue"), arg!.ToList()[1]);
         }
 
         [Fact]
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 b08cf6f..98a5fce 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/GraphTraversalSourceTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/GraphTraversalSourceTests.cs
@@ -22,7 +22,10 @@
 #endregion
 
 using System;
+using Gremlin.Net.Driver.Remote;
+using Gremlin.Net.Process.Remote;
 using Gremlin.Net.Process.Traversal;
+using Moq;
 using Xunit;
 
 namespace Gremlin.Net.UnitTest.Process.Traversal
@@ -57,7 +60,7 @@
         {
             var gLocal = AnonymousTraversalSource.Traversal();
 
-            var gRemote = gLocal.WithRemote(null);
+            var gRemote = gLocal.WithRemote(Mock.Of<IRemoteConnection>());
 
             Assert.Equal(0, gLocal.TraversalStrategies.Count);
             Assert.Equal(1, gRemote.TraversalStrategies.Count);
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/TestTraversal.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/TestTraversal.cs
index 51aac86..d618aec 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/TestTraversal.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/TestTraversal.cs
@@ -29,7 +29,7 @@
 {
     public class TestTraversal : DefaultTraversal<object, object>
     {
-        public TestTraversal(List<object> traverserObjs)
+        public TestTraversal(List<object?> traverserObjs)
         {
             var traversers = new List<Traverser>(traverserObjs.Count);
             traverserObjs.ForEach(o => traversers.Add(new Traverser(o)));
@@ -37,7 +37,7 @@
             Bytecode = new Bytecode();
         }
 
-        public TestTraversal(IReadOnlyList<object> traverserObjs, IReadOnlyList<long> traverserBulks)
+        public TestTraversal(IReadOnlyList<object?> traverserObjs, IReadOnlyList<long> traverserBulks)
         {
             var traversers = new List<Traverser>(traverserObjs.Count);
             traversers.AddRange(traverserObjs.Select((t, i) => new Traverser(t, traverserBulks[i])));
@@ -49,5 +49,7 @@
         {
             TraversalStrategies = traversalStrategies;
         }
+
+        public override Bytecode Bytecode { get; } = new();
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/TestTraversalStrategy.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/TestTraversalStrategy.cs
index 5a23409..697b285 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/TestTraversalStrategy.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/TestTraversalStrategy.cs
@@ -37,12 +37,12 @@
             _traversers = traversersToAddOnApplication;
         }
 
-        public void Apply<S, E>(ITraversal<S, E> traversal)
+        public void Apply<TStart, TEnd>(ITraversal<TStart, TEnd> traversal)
         {
             traversal.Traversers = _traversers;
         }
 
-        public Task ApplyAsync<S, E>(ITraversal<S, E> traversal, CancellationToken cancellationToken)
+        public Task ApplyAsync<TStart, TEnd>(ITraversal<TStart, TEnd> traversal, CancellationToken cancellationToken)
         {
             traversal.Traversers = _traversers;
             return Task.CompletedTask;
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/Translator/GroovyTranslatorTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/Translator/GroovyTranslatorTests.cs
index 0d4a56a..057e4f5 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/Translator/GroovyTranslatorTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/Translator/GroovyTranslatorTests.cs
@@ -420,6 +420,7 @@
             { _g.V().Has("runways", P.Inside(3, 5)), "g.V().has('runways', P.inside([3, 5]))" },

             { _g.V("44").OutE().ElementMap<object>(), "g.V('44').outE().elementMap()" },

             { _g.V("44").ValueMap<object, object>().By(__.Unfold<object>()), "g.V('44').valueMap().by(__.unfold())" },

+            { _g.V().E("1"), "g.V().E('1')" },

 

             // TODO: Support WithOptions

             {

@@ -485,7 +486,7 @@
         }

     }

 

-    private void AssertTranslation(string expectedTranslation, params object[] objs)

+    private void AssertTranslation(string expectedTranslation, params object?[]? objs)

     {

         AssertTraversalTranslation($"g.inject({expectedTranslation})", _g.Inject(objs));

     }

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 5f87dff..0ed745b 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/TraversalTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/TraversalTests.cs
@@ -36,7 +36,7 @@
         [InlineData("test")]
         public void ShouldReturnAvailableTraverserObjWhenNextIsCalled(object traverserObj)
         {
-            var traversal = new TestTraversal(new List<object> {traverserObj});
+            var traversal = new TestTraversal(new List<object?> {traverserObj});
 
             var actualObj = traversal.Next();
 
@@ -49,7 +49,7 @@
         [InlineData("test")]
         public void ShouldCheckHasNext(object traverserObj)
         {
-            var traversal = new TestTraversal(new List<object> {traverserObj});
+            var traversal = new TestTraversal(new List<object?> {traverserObj});
 
             Assert.True(traversal.HasNext());
             Assert.True(traversal.HasNext());
@@ -66,7 +66,7 @@
         [InlineData(10)]
         public void ShouldReturnCorrectNrOfResultObjsWhenNextIsCalledWithAmountArgument(int nrOfResults)
         {
-            var objs = new List<object>(20);
+            var objs = new List<object?>(20);
             for (var i = 0; i < 20; i++)
                 objs.Add(i);
             var traversal = new TestTraversal(objs);
@@ -79,9 +79,9 @@
                 Assert.Equal(objs[i], traversedObjsList[i]);
         }
 
-        private List<object> UnfoldBulks(IReadOnlyList<object> objs, IReadOnlyList<long> bulks)
+        private List<object?> UnfoldBulks(IReadOnlyList<object?> objs, IReadOnlyList<long> bulks)
         {
-            var unfoldedObjs = new List<object>();
+            var unfoldedObjs = new List<object?>();
             for (var traverserIdx = 0; traverserIdx < objs.Count; traverserIdx++)
             for (var currentBulkObjIdx = 0; currentBulkObjIdx < bulks[traverserIdx]; currentBulkObjIdx++)
                 unfoldedObjs.Add(objs[traverserIdx]);
@@ -91,7 +91,7 @@
         [Fact]
         public void ShouldDrainAllTraversersWhenIterateIsCalled()
         {
-            var someObjs = new List<object> {1, 2, 3};
+            var someObjs = new List<object?> {1, 2, 3};
             var traversal = new TestTraversal(someObjs);
 
             var drainedTraversal = traversal.Iterate();
@@ -103,7 +103,7 @@
         public void ShouldReturnNullWhenNextIsCalledAndNoTraverserIsAvailable()
         {
             var expectedFirstObj = 1;
-            var traversal = new TestTraversal(new List<object> {expectedFirstObj});
+            var traversal = new TestTraversal(new List<object?> {expectedFirstObj});
 
             var actualFirstObj = traversal.Next();
             var actualSecondObj = traversal.Next();
@@ -115,18 +115,18 @@
         [Fact]
         public void ShouldReturnTraversalsTraverserWhenNextTraverserIsCalled()
         {
-            var someObjs = new List<object> {1, 2, 3};
+            var someObjs = new List<object?> {1, 2, 3};
             var traversal = new TestTraversal(someObjs);
 
             var traverser = traversal.NextTraverser();
 
-            Assert.Equal(traversal.Traversers.First(), traverser);
+            Assert.Equal(traversal.Traversers!.First(), traverser);
         }
 
         [Fact]
         public void ShouldThrowNotSupportedExceptionWhenResetIsCalled()
         {
-            var someObjs = new List<object> {1, 2, 3};
+            var someObjs = new List<object?> {1, 2, 3};
             var traversal = new TestTraversal(someObjs);
 
             Assert.Throws<NotSupportedException>(() => traversal.Reset());
@@ -135,7 +135,7 @@
         [Fact]
         public void ShouldReturnAllTraverserObjsWhenToListIsCalled()
         {
-            var expectedObjs = new List<object> {1, 2, 3};
+            var expectedObjs = new List<object?> {1, 2, 3};
             var traversal = new TestTraversal(expectedObjs);
 
             var traversedObjs = traversal.ToList();
@@ -146,13 +146,13 @@
         [Fact]
         public void ShouldReturnAllTraverserObjWithoutDuplicatesWhenToSetIsCalled()
         {
-            var traverserObjs = new List<object> {1, 1, 2, 3};
+            var traverserObjs = new List<object?> {1, 1, 2, 3};
             var traversal = new TestTraversal(traverserObjs);
 
             var traversedObjSet = traversal.ToSet();
 
             Assert.Equal(3, traversedObjSet.Count);
-            Assert.Equal(new HashSet<object>(traverserObjs), traversedObjSet);
+            Assert.Equal(new HashSet<object?>(traverserObjs), traversedObjSet);
         }
 
         [Fact]
@@ -170,7 +170,7 @@
         [Fact]
         public void ShouldBeUnfoldTraverserBulksWhenToListIsCalled()
         {
-            var objs = new List<object> {1, 2, 3};
+            var objs = new List<object?> {1, 2, 3};
             var bulks = new List<long> {3, 2, 1};
             var traversal = new TestTraversal(objs, bulks);
 
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryMessageSerializerTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryMessageSerializerTests.cs
index 5510678..e175300 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryMessageSerializerTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryMessageSerializerTests.cs
@@ -77,7 +77,7 @@
             var serializer = CreateMessageSerializer();
 
             await Assert.ThrowsAsync<TaskCanceledException>(async () =>
-                await serializer.SerializeMessageAsync(RequestMessage.Build(default).Create(),
+                await serializer.SerializeMessageAsync(RequestMessage.Build(string.Empty).Create(),
                     new CancellationToken(true)));
         }
     
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryTests.cs
index 31b512a..47a190b 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/GraphBinaryTests.cs
@@ -26,11 +26,13 @@
 using System.Globalization;
 using System.IO;
 using System.Numerics;
+using System.Threading;
 using System.Threading.Tasks;
 using Gremlin.Net.Process.Traversal;
 using Gremlin.Net.Structure;
 using Gremlin.Net.Structure.IO.GraphBinary;
 using Xunit;
+using Barrier = Gremlin.Net.Process.Traversal.Barrier;
 using Path = Gremlin.Net.Structure.Path;
 
 namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary
@@ -76,7 +78,7 @@
             var writer = CreateGraphBinaryWriter();
             var serializationStream = new MemoryStream();
             
-            await writer.WriteValueAsync(value, serializationStream, false);
+            await writer.WriteNonNullableValueAsync(value, serializationStream);
 
             var serBytes = serializationStream.ToArray();
             Assert.Equal(expected, serBytes);
@@ -270,9 +272,9 @@
             var reader = CreateGraphBinaryReader();
             var serializationStream = new MemoryStream();
             
-            await writer.WriteValueAsync(expected, serializationStream, false);
+            await writer.WriteNonNullableValueAsync(expected, serializationStream);
             serializationStream.Position = 0;
-            var actual = await reader.ReadValueAsync<HashSet<string>>(serializationStream, false);
+            var actual = await reader.ReadNonNullableValueAsync<HashSet<string>>(serializationStream);
             
             Assert.Equal(expected, actual);
             Assert.Equal(expected.GetType(), actual.GetType());
@@ -349,9 +351,9 @@
             var reader = CreateGraphBinaryReader();
             var serializationStream = new MemoryStream();
             
-            await writer.WriteValueAsync(expected, serializationStream, false);
+            await writer.WriteNonNullableValueAsync(expected, serializationStream);
             serializationStream.Position = 0;
-            var actual = await reader.ReadValueAsync<Dictionary<string, int>>(serializationStream, false);
+            var actual = await reader.ReadNonNullableValueAsync<Dictionary<string, int>>(serializationStream);
             
             Assert.Equal(expected, actual);
             Assert.Equal(expected.GetType(), actual.GetType());
@@ -379,7 +381,7 @@
             var writer = CreateGraphBinaryWriter();
             var serializationStream = new MemoryStream();
 
-            await writer.WriteValueAsync(toSerialize, serializationStream, false);
+            await writer.WriteNonNullableValueAsync(toSerialize, serializationStream);
 
             var expected = new byte[]
                 {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
@@ -402,13 +404,12 @@
         }
         
         [Fact]
-        public async Task TestVertexWithNullLabel()
+        public async Task WriteNonNullableValueShouldThrowForNullValue()
         {
-            var expected = new Vertex(123, null);
             var writer = CreateGraphBinaryWriter();
             var serializationStream = new MemoryStream();
-            
-            await Assert.ThrowsAsync<IOException>(() => writer.WriteAsync(expected, serializationStream));
+
+            await Assert.ThrowsAsync<IOException>(() => writer.WriteNonNullableValueAsync(null!, serializationStream));
         }
         
         [Fact]
@@ -433,7 +434,7 @@
                 new Path(
                     new List<ISet<string>>
                         {new HashSet<string> {"a", "b"}, new HashSet<string> {"c", "d"}, new HashSet<string> {"e"}},
-                    new List<object> {1, 2, 3});
+                    new List<object?> {1, 2, 3});
             var writer = CreateGraphBinaryWriter();
             var reader = CreateGraphBinaryReader();
             var serializationStream = new MemoryStream();
@@ -668,9 +669,9 @@
             
             await writer.WriteAsync(expected, serializationStream);
             serializationStream.Position = 0;
-            var actual = (Bytecode) await reader.ReadAsync(serializationStream);
+            var actual = (Bytecode?) await reader.ReadAsync(serializationStream);
             
-            Assert.Equal(expected.SourceInstructions, actual.SourceInstructions);
+            Assert.Equal(expected.SourceInstructions, actual!.SourceInstructions);
             Assert.Equal(expected.StepInstructions, actual.StepInstructions);
         }
         
@@ -800,9 +801,9 @@
             
             await writer.WriteAsync(expected, serializationStream);
             serializationStream.Position = 0;
-            var actual = (StringBasedLambda) await reader.ReadAsync(serializationStream);
+            var actual = (StringBasedLambda?) await reader.ReadAsync(serializationStream);
             
-            Assert.Equal(expected.Language, actual.Language);
+            Assert.Equal(expected.Language, actual!.Language);
             Assert.Equal(expected.LambdaExpression, actual.LambdaExpression);
             Assert.Equal(expected.Arguments, actual.Arguments);
         }
@@ -817,9 +818,9 @@
             
             await writer.WriteAsync(expected, serializationStream);
             serializationStream.Position = 0;
-            var actual = (P) await reader.ReadAsync(serializationStream);
+            var actual = (P?) await reader.ReadAsync(serializationStream);
             
-            Assert.Equal(expected.OperatorName, actual.OperatorName);
+            Assert.Equal(expected.OperatorName, actual!.OperatorName);
             Assert.Equal(expected.Other, actual.Other);
             Assert.Equal(expected.Value, actual.Value);
         }
@@ -834,9 +835,9 @@
             
             await writer.WriteAsync(expected, serializationStream);
             serializationStream.Position = 0;
-            var actual = (P) await reader.ReadAsync(serializationStream);
+            var actual = (P?) await reader.ReadAsync(serializationStream);
             
-            Assert.Equal(expected.OperatorName, actual.OperatorName);
+            Assert.Equal(expected.OperatorName, actual!.OperatorName);
             Assert.Equal(expected.Other, actual.Other);
             Assert.Equal(expected.Value, actual.Value);
         }
@@ -851,9 +852,9 @@
             
             await writer.WriteAsync(expected, serializationStream);
             serializationStream.Position = 0;
-            var actual = (P) await reader.ReadAsync(serializationStream);
+            var actual = (P?) await reader.ReadAsync(serializationStream);
             
-            Assert.Equal(expected.ToString(), actual.ToString());
+            Assert.Equal(expected.ToString(), actual!.ToString());
         }
         
         [Fact]
@@ -866,9 +867,9 @@
             
             await writer.WriteAsync(expected, serializationStream);
             serializationStream.Position = 0;
-            var actual = (TextP) await reader.ReadAsync(serializationStream);
+            var actual = (TextP?) await reader.ReadAsync(serializationStream);
             
-            Assert.Equal(expected.OperatorName, actual.OperatorName);
+            Assert.Equal(expected.OperatorName, actual!.OperatorName);
             Assert.Equal(expected.Other, actual.Other);
             Assert.Equal(expected.Value, actual.Value);
         }
@@ -883,9 +884,9 @@
             
             await writer.WriteAsync(expected, serializationStream);
             serializationStream.Position = 0;
-            var actual = (Traverser) await reader.ReadAsync(serializationStream);
+            var actual = (Traverser?) await reader.ReadAsync(serializationStream);
             
-            Assert.Equal(expected.Object, actual.Object);
+            Assert.Equal(expected.Object, actual!.Object);
             Assert.Equal(expected.Bulk, actual.Bulk);
         }
         
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePerson.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePerson.cs
index e474f30..40627c8 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePerson.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePerson.cs
@@ -36,14 +36,14 @@
         public string Name { get; }
         public DateTimeOffset BirthDate { get; }
 
-        public bool Equals(SamplePerson other)
+        public bool Equals(SamplePerson? other)
         {
             if (ReferenceEquals(null, other)) return false;
             if (ReferenceEquals(this, other)) return true;
             return Name == other.Name && BirthDate.Equals(other.BirthDate);
         }
 
-        public override bool Equals(object obj)
+        public override bool Equals(object? obj)
         {
             if (ReferenceEquals(null, obj)) return false;
             if (ReferenceEquals(this, obj)) return true;
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePersonSerializer.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePersonSerializer.cs
index 4924808..172d167 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePersonSerializer.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePersonSerializer.cs
@@ -40,26 +40,38 @@
         {
             // Write {custom type info}, {value_flag} and {value}
             await stream.WriteAsync(_typeInfoBytes, cancellationToken).ConfigureAwait(false);
-            await WriteValueAsync(value, stream, writer, true, cancellationToken);
+            await WriteNullableValueAsync(value, stream, writer, cancellationToken);
         }
 
-        public override async Task WriteValueAsync(object value, Stream stream, GraphBinaryWriter writer, bool nullable,
+        public override async Task WriteNullableValueAsync(object value, Stream stream, GraphBinaryWriter writer,
             CancellationToken cancellationToken = default)
         {
             if (value == null)
             {
-                if (!nullable)
-                {
-                    throw new IOException("Unexpected null value when nullable is false");
-                }
-
                 await writer.WriteValueFlagNullAsync(stream, cancellationToken).ConfigureAwait(false);
                 return;
             }
 
-            if (nullable)
+            await writer.WriteValueFlagNoneAsync(stream, cancellationToken).ConfigureAwait(false);
+
+            var samplePerson = (SamplePerson)value;
+            var name = samplePerson.Name;
+            
+            // value_length = name_byte_length + name_bytes + long
+            await stream.WriteIntAsync(4 + Encoding.UTF8.GetBytes(name).Length + 8, cancellationToken)
+                .ConfigureAwait(false);
+
+            await writer.WriteNonNullableValueAsync(name, stream, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(samplePerson.BirthDate, stream, cancellationToken)
+                .ConfigureAwait(false);
+        }
+        
+        public override async Task WriteNonNullableValueAsync(object value, Stream stream, GraphBinaryWriter writer,
+            CancellationToken cancellationToken = default)
+        {
+            if (value == null)
             {
-                await writer.WriteValueFlagNoneAsync(stream, cancellationToken).ConfigureAwait(false);
+                throw new IOException("Unexpected null value when nullable is false");
             }
 
             var samplePerson = (SamplePerson)value;
@@ -69,12 +81,12 @@
             await stream.WriteIntAsync(4 + Encoding.UTF8.GetBytes(name).Length + 8, cancellationToken)
                 .ConfigureAwait(false);
 
-            await writer.WriteValueAsync(name, stream, false, cancellationToken).ConfigureAwait(false);
-            await writer.WriteValueAsync(samplePerson.BirthDate, stream, false, cancellationToken)
+            await writer.WriteNonNullableValueAsync(name, stream, cancellationToken).ConfigureAwait(false);
+            await writer.WriteNonNullableValueAsync(samplePerson.BirthDate, stream, cancellationToken)
                 .ConfigureAwait(false);
         }
 
-        public override async Task<object> ReadAsync(Stream stream, GraphBinaryReader reader,
+        public override async Task<object?> ReadAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
             // {custom type info}, {value_flag} and {value}
@@ -84,19 +96,16 @@
                 throw new IOException("{custom_type_info} should not be provided for this custom type");
             }
 
-            return await ReadValueAsync(stream, reader, true, cancellationToken).ConfigureAwait(false);
+            return await ReadNullableValueAsync(stream, reader, cancellationToken).ConfigureAwait(false);
         }
 
-        public override async Task<object> ReadValueAsync(Stream stream, GraphBinaryReader reader, bool nullable,
+        public override async Task<object?> ReadNullableValueAsync(Stream stream, GraphBinaryReader reader,
             CancellationToken cancellationToken = default)
         {
-            if (nullable)
+            var valueFlag = await stream.ReadByteAsync(cancellationToken).ConfigureAwait(false);
+            if ((valueFlag & 1) == 1)
             {
-                var valueFlag = await stream.ReadByteAsync(cancellationToken).ConfigureAwait(false);
-                if ((valueFlag & 1) == 1)
-                {
-                    return null;
-                }
+                return null;
             }
             
             // Read the byte length of the value bytes
@@ -112,10 +121,35 @@
                 throw new IOException($"Not enough readable bytes: {valueLength} (expected: {stream.Length})");
             }
 
-            var name = (string)await reader.ReadValueAsync<string>(stream, false, cancellationToken)
+            var name = (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken)
                 .ConfigureAwait(false);
             var birthDate =
-                (DateTimeOffset)await reader.ReadValueAsync<DateTimeOffset>(stream, false, cancellationToken)
+                (DateTimeOffset)await reader.ReadNonNullableValueAsync<DateTimeOffset>(stream, cancellationToken)
+                    .ConfigureAwait(false);
+
+            return new SamplePerson(name, birthDate);
+        }
+        
+        public override async Task<object> ReadNonNullableValueAsync(Stream stream, GraphBinaryReader reader,
+            CancellationToken cancellationToken = default)
+        {
+            // Read the byte length of the value bytes
+            var valueLength = await stream.ReadIntAsync(cancellationToken).ConfigureAwait(false);
+
+            if (valueLength <= 0)
+            {
+                throw new IOException($"Unexpected value length: {valueLength}");
+            }
+
+            if (valueLength > stream.Length)
+            {
+                throw new IOException($"Not enough readable bytes: {valueLength} (expected: {stream.Length})");
+            }
+
+            var name = (string)await reader.ReadNonNullableValueAsync<string>(stream, cancellationToken)
+                .ConfigureAwait(false);
+            var birthDate =
+                (DateTimeOffset)await reader.ReadNonNullableValueAsync<DateTimeOffset>(stream, cancellationToken)
                     .ConfigureAwait(false);
 
             return new SamplePerson(name, birthDate);
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePersonSerializerTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePersonSerializerTests.cs
index 06ccf25..cf7425d 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePersonSerializerTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary/Types/Sample/SamplePersonSerializerTests.cs
@@ -43,15 +43,13 @@
             
             await writer.WriteAsync(expected, serializationStream);
             serializationStream.Position = 0;
-            var actual = (SamplePerson) await reader.ReadAsync(serializationStream);
+            var actual = (SamplePerson?) await reader.ReadAsync(serializationStream);
             
             Assert.Equal(expected, actual);
         }
-
-        [Theory]
-        [InlineData(false)]
-        [InlineData(true)]
-        public async Task ReadValueAndWriteValueShouldBeSymmetric(bool nullable)
+        
+        [Fact]
+        public async Task ReadNullableValueAndWriteNullableValueShouldBeSymmetric()
         {
             var expected = new SamplePerson("Olivia", new DateTimeOffset(2010, 4, 29, 5, 30, 3, TimeSpan.FromHours(1)));
             var registry = TypeSerializerRegistry.Build()
@@ -60,9 +58,27 @@
             var reader = CreateGraphBinaryReader(registry);
             var serializationStream = new MemoryStream();
 
-            await writer.WriteValueAsync(expected, serializationStream, nullable).ConfigureAwait(false);
+            await writer.WriteNullableValueAsync(expected, serializationStream).ConfigureAwait(false);
             serializationStream.Position = 0;
-            var actual = (SamplePerson)await reader.ReadValueAsync<SamplePerson>(serializationStream, nullable)
+            var actual = (SamplePerson?)await reader.ReadNullableValueAsync<SamplePerson>(serializationStream)
+                .ConfigureAwait(false);
+            
+            Assert.Equal(expected, actual);
+        }
+
+        [Fact]
+        public async Task ReadNonNullableValueAndWriteNonNullableValueShouldBeSymmetric()
+        {
+            var expected = new SamplePerson("Olivia", new DateTimeOffset(2010, 4, 29, 5, 30, 3, TimeSpan.FromHours(1)));
+            var registry = TypeSerializerRegistry.Build()
+                .AddCustomType(typeof(SamplePerson), new SamplePersonSerializer()).Create();
+            var writer = CreateGraphBinaryWriter(registry);
+            var reader = CreateGraphBinaryReader(registry);
+            var serializationStream = new MemoryStream();
+
+            await writer.WriteNonNullableValueAsync(expected, serializationStream).ConfigureAwait(false);
+            serializationStream.Position = 0;
+            var actual = (SamplePerson)await reader.ReadNonNullableValueAsync<SamplePerson>(serializationStream)
                 .ConfigureAwait(false);
             
             Assert.Equal(expected, actual);
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 ad78334..da6a6a7 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
@@ -163,5 +163,7 @@
             Bytecode = bytecode;
             IsAnonymous = true;
         }
+
+        public override Bytecode Bytecode { get; }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSON3MessageSerializerTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSON3MessageSerializerTests.cs
index df75dc2..d1b593b 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSON3MessageSerializerTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/GraphSON3MessageSerializerTests.cs
@@ -38,7 +38,7 @@
         var serializer = CreateMessageSerializer();
 
         await Assert.ThrowsAsync<OperationCanceledException>(async () =>
-            await serializer.SerializeMessageAsync(RequestMessage.Build(default).Create(),
+            await serializer.SerializeMessageAsync(RequestMessage.Build(string.Empty).Create(),
                 new CancellationToken(true)));
     }
     
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 2c33a1e..82aeeb0 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
@@ -74,7 +74,7 @@
             var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSON);
             var deserializedValue = reader.ToObject(jsonElement);
         
-            Assert.Equal("test", deserializedValue.Value);
+            Assert.Equal("test", deserializedValue!.Value);
         }
         
         [Fact]
@@ -118,7 +118,7 @@
             var jsonElement = JsonSerializer.Deserialize<JsonElement>(serializedDict);
             var deserializedValue = reader.ToObject(jsonElement);
         
-            var expectedDict = new Dictionary<string, dynamic>
+            var expectedDict = new Dictionary<string, dynamic?>
             {
                 {"age", new List<object> {29}},
                 {"name", new List<object> {"marko"}},
@@ -136,7 +136,7 @@
             var reader = CreateStandardGraphSONReader(version);
         
             var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
-            Edge readEdge = reader.ToObject(jsonElement);
+            Edge readEdge = reader.ToObject(jsonElement)!;
         
             Assert.Equal((long) 17, readEdge.Id);
             Assert.Equal("knows", readEdge.Label);
@@ -286,7 +286,7 @@
             var jsonElement = JsonSerializer.Deserialize<JsonElement>(serializedValue);
             var deserializedValue = reader.ToObject(jsonElement);
         
-            Assert.Equal(new List<object> {5, 6, null}, deserializedValue);
+            Assert.Equal(new List<object?> {5, 6, null}, deserializedValue);
         }
         
         [Theory, MemberData(nameof(Versions))]
@@ -296,7 +296,7 @@
             var reader = CreateStandardGraphSONReader(version);
         
             var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
-            T readT = reader.ToObject(jsonElement);
+            T readT = reader.ToObject(jsonElement)!;
         
             Assert.Equal(T.Label, readT);
         }
@@ -333,7 +333,7 @@
             var reader = CreateStandardGraphSONReader(2);
         
             var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
-            Path readPath = reader.ToObject(jsonElement);
+            Path readPath = reader.ToObject(jsonElement)!;
         
             Assert.Equal("path[v[1], v[3], lop]", readPath.ToString());
             Assert.Equal(new Vertex(1), readPath[0]);
@@ -351,7 +351,7 @@
             var reader = CreateStandardGraphSONReader(3);
         
             var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
-            Path readPath = reader.ToObject(jsonElement);
+            Path readPath = reader.ToObject(jsonElement)!;
         
             Assert.Equal("path[v[5]]", readPath.ToString());
             Assert.Equal(new Vertex(5L), readPath[0]);
@@ -370,13 +370,13 @@
             var reader = CreateStandardGraphSONReader(version);
         
             var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
-            Property readProperty = reader.ToObject(jsonElement);
+            Property readProperty = reader.ToObject(jsonElement)!;
         
             Assert.Equal("aKey", readProperty.Key);
             Assert.Equal((long) 17, readProperty.Value);
-            Assert.Equal(typeof(Edge), readProperty.Element.GetType());
+            Assert.Equal(typeof(Edge), readProperty.Element!.GetType());
             var edge = readProperty.Element as Edge;
-            Assert.Equal((long) 122, edge.Id);
+            Assert.Equal((long) 122, edge!.Id);
             Assert.Equal("knows", edge.Label);
             Assert.Equal("x", edge.InV.Id);
             Assert.Equal("y", edge.OutV.Id);
@@ -415,7 +415,7 @@
             var reader = CreateStandardGraphSONReader(version);
         
             var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
-            VertexProperty readVertexProperty = reader.ToObject(jsonElement);
+            VertexProperty readVertexProperty = reader.ToObject(jsonElement)!;
         
             Assert.Equal("anId", readVertexProperty.Id);
             Assert.Equal("aKey", readVertexProperty.Label);
@@ -431,7 +431,7 @@
             var reader = CreateStandardGraphSONReader(version);
         
             var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
-            VertexProperty readVertexProperty = reader.ToObject(jsonElement);
+            VertexProperty readVertexProperty = reader.ToObject(jsonElement)!;
         
             Assert.Equal(1, readVertexProperty.Id);
             Assert.Equal("name", readVertexProperty.Label);
@@ -460,7 +460,7 @@
             var reader = CreateStandardGraphSONReader(version);
         
             var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
-            Vertex deserializedValue = reader.ToObject(jsonElement);
+            Vertex deserializedValue = reader.ToObject(jsonElement)!;
         
             Assert.Equal("person", deserializedValue.Label);
         }
@@ -473,11 +473,11 @@
             var reader = CreateStandardGraphSONReader(version);
         
             var jsonElement = JsonSerializer.Deserialize<JsonElement>(graphSon);
-            Vertex readVertex = reader.ToObject(jsonElement);
+            Vertex readVertex = reader.ToObject(jsonElement)!;
         
             Assert.Equal(new Vertex(1), readVertex);
             Assert.Equal("person", readVertex.Label);
-            Assert.Equal(typeof(int), readVertex.Id.GetType());
+            Assert.Equal(typeof(int), readVertex.Id!.GetType());
         }
         
         [Theory, MemberData(nameof(VersionsSupportingCollections))]
@@ -576,7 +576,7 @@
             var reader = CreateStandardGraphSONReader(version);
         
             var jsonElement = JsonSerializer.Deserialize<JsonElement>(json);
-            Traverser deserializedValue = reader.ToObject(jsonElement);
+            Traverser deserializedValue = reader.ToObject(jsonElement)!;
             
             Assert.Equal(10, deserializedValue.Bulk);
             Assert.Equal(1, deserializedValue.Object);
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 9247831..3a42823 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
@@ -295,7 +295,7 @@
         public void ShouldSerializeGList(int version)
         {
             var writer = CreateGraphSONWriter(version);
-            var list = new List<object> {5, 6, null};
+            var list = new List<object?> {5, 6, null};
 
             var serializedGraphSON = writer.WriteObject(list);
 
@@ -552,7 +552,7 @@
 
     internal class TestGraphSONSerializer : IGraphSONSerializer
     {
-        public string TestNamespace { get; set; }
+        public string? TestNamespace { get; set; }
 
         public Dictionary<string, dynamic> Dictify(dynamic objectData, GraphSONWriter writer)
         {
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/TestClass.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/TestClass.cs
index 13d1bca..1fba943 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/TestClass.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphSON/TestClass.cs
@@ -25,6 +25,6 @@
 {
     internal class TestClass
     {
-        public dynamic Value { get; set; }
+        public dynamic? Value { get; set; }
     }
 }
\ No newline at end of file
diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/PathTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/PathTests.cs
index 6df92ba..a996df1 100644
--- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/PathTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/PathTests.cs
@@ -40,7 +40,7 @@
                 new HashSet<string> {"c", "b"},
                 new HashSet<string>()
             };
-            var objects = new List<object> {1, new Vertex(1), "hello"};
+            var objects = new List<object?> {1, new Vertex(1), "hello"};
 
             var path = new Path(labels, objects);
 
@@ -57,7 +57,7 @@
                 new HashSet<string> {"c", "b"},
                 new HashSet<string>()
             };
-            var path = new Path(labels, new List<object>());
+            var path = new Path(labels, new List<object?>());
 
             var containsKey = path.ContainsKey("c");
 
@@ -73,7 +73,7 @@
                 new HashSet<string> {"c", "b"},
                 new HashSet<string>()
             };
-            var path = new Path(labels, new List<object>());
+            var path = new Path(labels, new List<object?>());
 
             var containsKey = path.ContainsKey("z");
 
@@ -83,7 +83,7 @@
         [Fact]
         public void ShouldReturnCountOfObjectsForCountProperty()
         {
-            var objects = new List<object> {1, new Vertex(1), "hello"};
+            var objects = new List<object?> {1, new Vertex(1), "hello"};
             var path = new Path(new List<ISet<string>>(), objects);
 
             var count = path.Count;
@@ -94,7 +94,7 @@
         [Fact]
         public void ShouldEnumeratorObjectsIntoListWhenToListIsCalled()
         {
-            var objects = new List<object> {1, new Vertex(1), "hello"};
+            var objects = new List<object?> {1, new Vertex(1), "hello"};
             var path = new Path(new List<ISet<string>>(), objects);
 
             var enumeratedObj = path.ToList();
@@ -112,7 +112,7 @@
                         new HashSet<string> {"a", "b"},
                         new HashSet<string> {"c", "b"},
                         new HashSet<string>()
-                    }, new List<object> {1, new Vertex(1), "hello"});
+                    }, new List<object?> {1, new Vertex(1), "hello"});
             var secondPath =
                 new Path(
                     new List<ISet<string>>
@@ -120,7 +120,7 @@
                         new HashSet<string> {"a", "b"},
                         new HashSet<string> {"c", "b"},
                         new HashSet<string>()
-                    }, new List<object> {1, new Vertex(1), "hello"});
+                    }, new List<object?> {1, new Vertex(1), "hello"});
 
             var equals = firstPath.Equals(secondPath);
 
@@ -137,7 +137,7 @@
                         new HashSet<string> {"a", "b"},
                         new HashSet<string> {"c", "b"},
                         new HashSet<string>()
-                    }, new List<object> {1, new Vertex(1), "hello"});
+                    }, new List<object?> {1, new Vertex(1), "hello"});
             var secondPath =
                 new Path(
                     new List<ISet<string>>
@@ -145,7 +145,7 @@
                         new HashSet<string> {"a"},
                         new HashSet<string> {"c", "b"},
                         new HashSet<string>()
-                    }, new List<object> {1, new Vertex(1), "hello"});
+                    }, new List<object?> {1, new Vertex(1), "hello"});
 
             var equals = firstPath.Equals(secondPath);
 
@@ -162,7 +162,7 @@
                         new HashSet<string> {"a", "b"},
                         new HashSet<string> {"c", "b"},
                         new HashSet<string>()
-                    }, new List<object> {1, new Vertex(1), "hello"});
+                    }, new List<object?> {1, new Vertex(1), "hello"});
             var secondPath =
                 new Path(
                     new List<ISet<string>>
@@ -170,7 +170,7 @@
                         new HashSet<string> {"a", "b"},
                         new HashSet<string> {"c", "b"},
                         new HashSet<string>()
-                    }, new List<object> {3, new Vertex(1), "hello"});
+                    }, new List<object?> {3, new Vertex(1), "hello"});
 
             var equals = firstPath.Equals(secondPath);
 
@@ -187,7 +187,7 @@
                         new HashSet<string> {"a", "b"},
                         new HashSet<string> {"c", "b"},
                         new HashSet<string>()
-                    }, new List<object> { 1, new Vertex(1), "hello" });
+                    }, new List<object?> { 1, new Vertex(1), "hello" });
             object secondPath =
                 new Path(
                     new List<ISet<string>>
@@ -195,7 +195,7 @@
                         new HashSet<string> {"a", "b"},
                         new HashSet<string> {"c", "b"},
                         new HashSet<string>()
-                    }, new List<object> { 1, new Vertex(1), "hello" });
+                    }, new List<object?> { 1, new Vertex(1), "hello" });
 
             var equals = firstPath.Equals(secondPath);
 
@@ -212,7 +212,7 @@
                         new HashSet<string> {"a", "b"},
                         new HashSet<string> {"c", "b"},
                         new HashSet<string>()
-                    }, new List<object> { 1, new Vertex(1), "hello" });
+                    }, new List<object?> { 1, new Vertex(1), "hello" });
             object secondPath =
                 new Path(
                     new List<ISet<string>>
@@ -220,7 +220,7 @@
                         new HashSet<string> {"a"},
                         new HashSet<string> {"c", "b"},
                         new HashSet<string>()
-                    }, new List<object> { 1, new Vertex(1), "hello" });
+                    }, new List<object?> { 1, new Vertex(1), "hello" });
 
             var equals = firstPath.Equals(secondPath);
 
@@ -237,7 +237,7 @@
                         new HashSet<string> {"a", "b"},
                         new HashSet<string> {"c", "b"},
                         new HashSet<string>()
-                    }, new List<object> { 1, new Vertex(1), "hello" });
+                    }, new List<object?> { 1, new Vertex(1), "hello" });
             object secondPath =
                 new Path(
                     new List<ISet<string>>
@@ -245,7 +245,7 @@
                         new HashSet<string> {"a", "b"},
                         new HashSet<string> {"c", "b"},
                         new HashSet<string>()
-                    }, new List<object> { 3, new Vertex(1), "hello" });
+                    }, new List<object?> { 3, new Vertex(1), "hello" });
 
             var equals = firstPath.Equals(secondPath);
 
@@ -255,7 +255,7 @@
         [Fact]
         public void ShouldReturnFalseForEqualsWhereOtherIsNull()
         {
-            var path = new Path(new List<ISet<string>> {new HashSet<string> {"a", "b"},}, new List<object> {1});
+            var path = new Path(new List<ISet<string>> { new HashSet<string> { "a", "b" }, }, new List<object?> { 1 });
 
             var equals = path.Equals(null);
 
@@ -272,7 +272,7 @@
                         new HashSet<string> {"a", "b"},
                         new HashSet<string> {"c", "b"},
                         new HashSet<string>()
-                    }, new List<object> { 1, new Vertex(1), "hello" });
+                    }, new List<object?> { 1, new Vertex(1), "hello" });
             var secondPath =
                 new Path(
                     new List<ISet<string>>
@@ -280,7 +280,7 @@
                         new HashSet<string> {"a", "b"},
                         new HashSet<string> {"c", "b"},
                         new HashSet<string>()
-                    }, new List<object> { 1, new Vertex(1), "hello" });
+                    }, new List<object?> { 1, new Vertex(1), "hello" });
 
             var firstHashCode = firstPath.GetHashCode();
             var secondHashCode = secondPath.GetHashCode();
@@ -291,7 +291,7 @@
         [Fact]
         public void ShouldThrowWhenInvalidIndexIsAccessed()
         {
-            var objects = new List<object> {1, new Vertex(1), "hello"};
+            var objects = new List<object?> {1, new Vertex(1), "hello"};
             var path = new Path(new List<ISet<string>>(), objects);
 
             Assert.Throws<ArgumentOutOfRangeException>(() => path[3]);
@@ -300,7 +300,7 @@
         [Fact]
         public void ShouldReturnObjectsByTheirIndex()
         {
-            var objects = new List<object> {1, new Vertex(1), "hello"};
+            var objects = new List<object?> {1, new Vertex(1), "hello"};
             var path = new Path(new List<ISet<string>>(), objects);
 
             Assert.Equal(1, path[0]);
@@ -317,7 +317,7 @@
                 new HashSet<string> {"c", "b"},
                 new HashSet<string>()
             };
-            var objects = new List<object> {1, new Vertex(1), "hello"};
+            var objects = new List<object?> {1, new Vertex(1), "hello"};
             var path = new Path(labels, objects);
 
             var bObjects = path["b"];
@@ -334,7 +334,7 @@
                 new HashSet<string> {"c", "b"},
                 new HashSet<string>()
             };
-            var objects = new List<object> {1, new Vertex(1), "hello"};
+            var objects = new List<object?> {1, new Vertex(1), "hello"};
             var path = new Path(labels, objects);
 
             Assert.Equal(1, path["a"]);
@@ -345,7 +345,7 @@
         [Fact]
         public void ShouldThrowWhenUnknownKeyIsAccessed()
         {
-            var path = new Path(new List<ISet<string>>(), new List<object>());
+            var path = new Path(new List<ISet<string>>(), new List<object?>());
 
             Assert.Throws<KeyNotFoundException>(() => path["unknownKey"]);
         }
@@ -359,7 +359,7 @@
                 new HashSet<string> {"c", "b"},
                 new HashSet<string>()
             };
-            var objects = new List<object> {1, new Vertex(1), "hello"};
+            var objects = new List<object?> {1, new Vertex(1), "hello"};
             var path = new Path(labels, objects);
 
             var pathStr = path.ToString();
@@ -376,10 +376,10 @@
                 new HashSet<string> {"c", "b"},
                 new HashSet<string>()
             };
-            var objects = new List<object> {1, new Vertex(1), "hello"};
+            var objects = new List<object?> {1, new Vertex(1), "hello"};
             var path = new Path(labels, objects);
 
-            var success = path.TryGetValue("b", out object actualObj);
+            var success = path.TryGetValue("b", out object? actualObj);
 
             Assert.True(success);
             Assert.Equal(new List<object> {1, new Vertex(1)}, actualObj);
@@ -394,10 +394,10 @@
                 new HashSet<string> {"c", "b"},
                 new HashSet<string>()
             };
-            var objects = new List<object> {1, new Vertex(1), "hello"};
+            var objects = new List<object?> {1, new Vertex(1), "hello"};
             var path = new Path(labels, objects);
 
-            var success = path.TryGetValue("b", out object actualObj);
+            var success = path.TryGetValue("b", out var actualObj);
 
             Assert.True(success);
             Assert.Equal(new Vertex(1), actualObj);
@@ -406,9 +406,9 @@
         [Fact]
         public void ShouldReturnFalseForTryGetWhenUnknownKeyIsProvided()
         {
-            var path = new Path(new List<ISet<string>>(), new List<object>());
+            var path = new Path(new List<ISet<string>>(), new List<object?>());
 
-            var success = path.TryGetValue("unknownKey", out object _);
+            var success = path.TryGetValue("unknownKey", out _);
 
             Assert.False(success);
         }
diff --git a/gremlin-dotnet/test/pom.xml b/gremlin-dotnet/test/pom.xml
index 55e41d3..cd63f32 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.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-dotnet-tests</artifactId>
     <name>Apache TinkerPop :: Gremlin.Net - Tests</name>
@@ -177,7 +177,7 @@
                                 <scope>runtime</scope>
                             </dependency>
                             <dependency>
-                                <groupId>org.codehaus.groovy</groupId>
+                                <groupId>org.apache.groovy</groupId>
                                 <artifactId>groovy-all</artifactId>
                                 <version>${groovy.version}</version>
                                 <type>pom</type>
diff --git a/gremlin-driver/pom.xml b/gremlin-driver/pom.xml
index a20842d..94a0f4b 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.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-driver</artifactId>
     <name>Apache TinkerPop :: Gremlin Driver</name>
@@ -32,6 +32,11 @@
             <version>${project.version}</version>
         </dependency>
         <dependency>
+            <groupId>org.apache.tinkerpop</groupId>
+            <artifactId>gremlin-util</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
             <groupId>io.netty</groupId>
             <artifactId>netty-all</artifactId>
             <version>${netty.version}</version>
@@ -60,6 +65,12 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.tinkerpop</groupId>
+            <artifactId>gremlin-socket-server</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <scope>test</scope>
@@ -70,21 +81,17 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-inline</artifactId>
+            <version>4.10.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>io.github.hakky54</groupId>
             <artifactId>logcaptor</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.powermock</groupId>
-            <artifactId>powermock-module-junit4</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.powermock</groupId>
-            <artifactId>powermock-api-mockito2</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>org.hamcrest</groupId>
             <artifactId>hamcrest</artifactId>
             <scope>test</scope>
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 513ec92..d522e2c 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
@@ -19,11 +19,12 @@
 package org.apache.tinkerpop.gremlin.driver;
 
 import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.apache.tinkerpop.gremlin.util.Tokens;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.tinkerpop.gremlin.driver.exception.ConnectionException;
 import org.apache.tinkerpop.gremlin.driver.exception.NoHostAvailableException;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
@@ -362,6 +363,7 @@
         options.getOverrideRequestId().ifPresent(request::overrideRequestId);
         options.getUserAgent().ifPresent(userAgent -> request.addArg(Tokens.ARGS_USER_AGENT, userAgent));
         options.getLanguage().ifPresent(lang -> request.addArg(Tokens.ARGS_LANGUAGE, lang));
+        options.getMaterializeProperties().ifPresent(mp -> request.addArg(Tokens.ARGS_MATERIALIZE_PROPERTIES, mp));
 
         return submitAsync(request.create());
     }
@@ -659,6 +661,7 @@
                 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));
+                options.getMaterializeProperties().ifPresent(mp -> request.addArg(Tokens.ARGS_MATERIALIZE_PROPERTIES, mp));
 
                 return submitAsync(request.create());
             } catch (RuntimeException re) {
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 3ed867a..8953a7e 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
@@ -26,8 +26,10 @@
 import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
 import io.netty.util.concurrent.Future;
 import org.apache.commons.configuration2.Configuration;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
-import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.ser.Serializers;
 import io.netty.bootstrap.Bootstrap;
 import io.netty.channel.nio.NioEventLoopGroup;
 import org.apache.commons.lang3.concurrent.BasicThreadFactory;
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 056c53c..db79fe0 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
@@ -18,10 +18,11 @@
  */
 package org.apache.tinkerpop.gremlin.driver;
 
+import org.apache.tinkerpop.gremlin.util.Tokens;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.tinkerpop.gremlin.driver.exception.ConnectionException;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 import io.netty.bootstrap.Bootstrap;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFutureListener;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ConnectionPool.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ConnectionPool.java
index 21bce9c..ee31353 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ConnectionPool.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ConnectionPool.java
@@ -21,8 +21,8 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.tinkerpop.gremlin.driver.exception.ConnectionException;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.util.ExceptionHelper;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.util.TimeUtil;
 
 import java.util.ArrayList;
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 cb11c4e..c76a20e 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
@@ -21,15 +21,16 @@
 import io.netty.util.AttributeMap;
 import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.tinkerpop.gremlin.driver.exception.ResponseException;
-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.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.SimpleChannelInboundHandler;
 import io.netty.util.Attribute;
 import io.netty.util.AttributeKey;
 import io.netty.util.ReferenceCountUtil;
-import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
+import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/LoadBalancingStrategy.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/LoadBalancingStrategy.java
index c6ad4bd..4455a4e 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/LoadBalancingStrategy.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/LoadBalancingStrategy.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.driver;
 
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 
 import java.util.ArrayList;
 import java.util.Collection;
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 ac923f9..63d7dad 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
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.driver;
 
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -41,6 +41,7 @@
     private final UUID overrideRequestId;
     private final String userAgent;
     private final String language;
+    private final String materializeProperties;
 
     private RequestOptions(final Builder builder) {
         this.aliases = builder.aliases;
@@ -50,6 +51,7 @@
         this.overrideRequestId = builder.overrideRequestId;
         this.userAgent = builder.userAgent;
         this.language = builder.language;
+        this.materializeProperties = builder.materializeProperties;
     }
 
     public Optional<UUID> getOverrideRequestId() {
@@ -80,6 +82,8 @@
         return Optional.ofNullable(language);
     }
 
+    public Optional<String> getMaterializeProperties() { return Optional.ofNullable(materializeProperties); }
+
     public static Builder build() {
         return new Builder();
     }
@@ -91,6 +95,7 @@
         private Long timeout = null;
         private UUID overrideRequestId = null;
         private String userAgent = null;
+        private String materializeProperties = null;
         private String language = null;
         private boolean maintainStateAfterException = false;
 
@@ -159,6 +164,14 @@
             return this;
         }
 
+        /**
+         * Sets the materializeProperties identifier to be sent on the request.
+         */
+        public Builder materializeProperties(final String materializeProperties) {
+            this.materializeProperties = materializeProperties;
+            return this;
+        }
+
         public RequestOptions create() {
             return new RequestOptions(this);
         }
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Result.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Result.java
index 58793e8..4c34aad 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Result.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Result.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.driver;
 
-import org.apache.tinkerpop.gremlin.driver.message.ResponseResult;
+import org.apache.tinkerpop.gremlin.util.message.ResponseResult;
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Element;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ResultSet.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ResultSet.java
index 01a900b..4d60b8d 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ResultSet.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ResultSet.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.driver;
 
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 
 import java.util.ArrayList;
 import java.util.Collections;
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 130c878..66f6d95 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
@@ -19,7 +19,8 @@
 package org.apache.tinkerpop.gremlin.driver;
 
 import org.apache.commons.configuration2.Configuration;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 import org.yaml.snakeyaml.LoaderOptions;
 import org.yaml.snakeyaml.TypeDescription;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/exception/ResponseException.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/exception/ResponseException.java
index a960d44..fc4b5d5 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/exception/ResponseException.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/exception/ResponseException.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.driver.exception;
 
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 
 import java.util.Collections;
 import java.util.List;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketGremlinRequestEncoder.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketGremlinRequestEncoder.java
index 8bb8173..05226f7 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketGremlinRequestEncoder.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketGremlinRequestEncoder.java
@@ -18,11 +18,11 @@
  */
 package org.apache.tinkerpop.gremlin.driver.handler;
 
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.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 org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.ser.MessageTextSerializer;
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandler;
 import io.netty.channel.ChannelHandlerContext;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketGremlinResponseDecoder.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketGremlinResponseDecoder.java
index 2e93061..3ef1eed 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketGremlinResponseDecoder.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketGremlinResponseDecoder.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.driver.handler;
 
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
-import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.ser.MessageTextSerializer;
 import io.netty.channel.ChannelHandler;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.MessageToMessageDecoder;
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 13cc23d..dd0a925 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
@@ -38,10 +38,12 @@
 import java.util.UUID;
 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_EVAL_TIMEOUT;
-import static org.apache.tinkerpop.gremlin.driver.Tokens.ARGS_USER_AGENT;
-import static org.apache.tinkerpop.gremlin.driver.Tokens.REQUEST_ID;
+import static org.apache.tinkerpop.gremlin.util.Tokens.ARGS_BATCH_SIZE;
+import static org.apache.tinkerpop.gremlin.util.Tokens.ARGS_EVAL_TIMEOUT;
+import static org.apache.tinkerpop.gremlin.util.Tokens.ARGS_USER_AGENT;
+import static org.apache.tinkerpop.gremlin.util.Tokens.REQUEST_ID;
+import static org.apache.tinkerpop.gremlin.util.Tokens.ARGS_MATERIALIZE_PROPERTIES;
+
 
 /**
  * A {@link RemoteConnection} implementation for Gremlin Server. Each {@code DriverServerConnection} is bound to one
@@ -258,6 +260,8 @@
                 builder.batchSize(((Number) options.get(ARGS_BATCH_SIZE)).intValue());
             if (options.containsKey(ARGS_USER_AGENT))
                 builder.userAgent((String) options.get(ARGS_USER_AGENT));
+            if (options.containsKey(ARGS_MATERIALIZE_PROPERTIES))
+                builder.materializeProperties((String) options.get(ARGS_MATERIALIZE_PROPERTIES));
         }
         return builder.create();
     }
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/simple/AbstractClient.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/simple/AbstractClient.java
index 270277b..00a67b4 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/simple/AbstractClient.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/simple/AbstractClient.java
@@ -23,9 +23,9 @@
 import io.netty.channel.SimpleChannelInboundHandler;
 import io.netty.channel.nio.NioEventLoopGroup;
 import org.apache.commons.lang3.concurrent.BasicThreadFactory;
-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.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/simple/SimpleClient.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/simple/SimpleClient.java
index 9a01c5c..43ace82 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/simple/SimpleClient.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/simple/SimpleClient.java
@@ -18,9 +18,9 @@
  */
 package org.apache.tinkerpop.gremlin.driver.simple;
 
-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.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
 
 import java.io.Closeable;
 import java.util.List;
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 78f4268..2f38978 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,11 +21,11 @@
 import io.netty.buffer.PooledByteBufAllocator;
 import io.netty.channel.ChannelOption;
 import io.netty.handler.codec.http.EmptyHttpHeaders;
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
 import org.apache.tinkerpop.gremlin.driver.handler.WebSocketClientHandler;
 import org.apache.tinkerpop.gremlin.driver.handler.WebSocketGremlinRequestEncoder;
 import org.apache.tinkerpop.gremlin.driver.handler.WebSocketGremlinResponseDecoder;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 import io.netty.bootstrap.Bootstrap;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelInitializer;
@@ -36,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.GraphBinaryMessageSerializerV1;
+import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryMapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
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 3766460..1a3b346 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
@@ -23,7 +23,7 @@
 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.ser.Serializers;
+import org.apache.tinkerpop.gremlin.util.ser.Serializers;
 import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
 
 import java.io.BufferedWriter;
diff --git a/gremlin-driver/src/main/static/NOTICE b/gremlin-driver/src/main/static/NOTICE
index 82a0008..433dc70 100644
--- a/gremlin-driver/src/main/static/NOTICE
+++ b/gremlin-driver/src/main/static/NOTICE
@@ -17,7 +17,7 @@
    (Apache license)
 
 ------------------------------------------------------------------------
-Jackson-Databind and Jackson-Core 2.14.0 (Included through gremlin-shaded)
+Jackson-Databind 2.14.0 and Jackson-Core - shaded in gremlin-shaded to org.apache.tinkerpop.shaded.jackson
 ------------------------------------------------------------------------
 It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has
 been in development since 2007.
@@ -34,6 +34,6 @@
 Copyright 2014 The Netty Project
 
 ------------------------------------------------------------------------
-Objenesis 2.4 (Included through gremlin-shaded)
+Objenesis 3.3 - shaded in gremlin-shaded to org.apache.tinkerpop.shaded.objenesis
 ------------------------------------------------------------------------
-Copyright 2006-2016 Joe Walnes, Henri Tremblay, Leonardo Mesquita
+Copyright 2006-2022 Joe Walnes, Henri Tremblay, Leonardo Mesquita
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ClientTest.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ClientTest.java
deleted file mode 100644
index b69d321..0000000
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ClientTest.java
+++ /dev/null
@@ -1,88 +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;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.powermock.core.classloader.annotations.PowerMockIgnore;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-import org.apache.tinkerpop.gremlin.driver.exception.NoHostAvailableException;
-
-import java.util.Collections;
-import java.util.Optional;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-
-import static org.mockito.Mockito.when;
-import static org.powermock.api.mockito.PowerMockito.whenNew;
-
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({Client.ClusteredClient.class, Client.SessionedClient.class, Host.class, Cluster.class})
-@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"})
-public class ClientTest {
-    @Mock
-    private Cluster cluster;
-
-    @Mock
-    private Host mockAvailableHost;
-
-    @Mock
-    private Client.Settings settings;
-
-    private ScheduledExecutorService executor;
-    private ScheduledExecutorService scheduler;
-
-    @Before
-    public void setup() {
-        executor = Executors.newScheduledThreadPool(1);
-        scheduler = Executors.newScheduledThreadPool(1);
-        when(mockAvailableHost.isAvailable()).thenReturn(true);
-        when(cluster.allHosts()).thenReturn(Collections.singletonList(mockAvailableHost));
-        when(cluster.executor()).thenReturn(executor);
-        when(cluster.hostScheduler()).thenReturn(scheduler);
-    }
-
-    @After
-    public void cleanup() {
-        executor.shutdown();
-        scheduler.shutdown();
-    }
-
-    @Test(expected = NoHostAvailableException.class)
-    public void shouldThrowErrorWhenConnPoolInitFailsForClusteredClient() throws Exception {
-        Client.ClusteredClient client = new Client.ClusteredClient(cluster, settings);
-        whenNew(ConnectionPool.class).withAnyArguments().thenThrow(new RuntimeException("cannot initialize client"));
-        client.init();
-    }
-
-    @Test(expected = NoHostAvailableException.class)
-    public void shouldThrowErrorWhenConnPoolInitFailsForSessionClient() throws Exception {
-        final Client.SessionSettings sessionSettings = Client.SessionSettings.build().sessionId("my-session-id").create();
-        when(settings.getSession()).thenReturn(Optional.of(sessionSettings));
-        Client.SessionedClient client = new Client.SessionedClient(cluster, settings);
-        whenNew(ConnectionPool.class).withAnyArguments().thenThrow(new RuntimeException("cannot initialize client"));
-        client.init();
-    }
-
-}
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/RequestMessageTest.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/RequestMessageTest.java
index d6b47c9..a6ccb58 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/RequestMessageTest.java
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/RequestMessageTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.driver;
 
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 import org.junit.Assert;
 import org.junit.Test;
 
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ResultSetTest.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ResultSetTest.java
index 115736e..50e8769 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ResultSetTest.java
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ResultSetTest.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.driver;
 
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 import org.junit.Before;
 import org.junit.Test;
 
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/SerializationExceptionTest.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/SerializationExceptionTest.java
index ba25279..c6a6364 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/SerializationExceptionTest.java
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/SerializationExceptionTest.java
@@ -21,7 +21,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
-import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
+import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
 import org.junit.Test;
 
 import java.io.IOException;
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/TestWSGremlinInitializer.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/TestWSGremlinInitializer.java
deleted file mode 100644
index eda187c..0000000
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/TestWSGremlinInitializer.java
+++ /dev/null
@@ -1,186 +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;
-
-import io.netty.buffer.ByteBufAllocator;
-import io.netty.buffer.UnpooledByteBufAllocator;
-import io.netty.handler.codec.http.HttpHeaders;
-import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-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.driver.ser.GraphSONMessageSerializerV2d0;
-import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelPipeline;
-import io.netty.handler.codec.MessageToMessageDecoder;
-import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
-import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
-import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
-
-import java.util.List;
-import java.util.UUID;
-
-
-/**
- * Initializer which partially mimics the Gremlin Server. This initializer injects a handler in the
- * server pipeline that can be modified to send the desired response for a test case.
- */
-public class TestWSGremlinInitializer extends TestChannelizers.TestWebSocketServerInitializer {
-    private static final Logger logger = LoggerFactory.getLogger(TestWSGremlinInitializer.class);
-    /**
-     * If a request with this ID comes to the server, the server responds back with a single vertex picked from Modern
-     * graph.
-     */
-    public static final UUID SINGLE_VERTEX_REQUEST_ID =
-            UUID.fromString("6457272A-4018-4538-B9AE-08DD5DDC0AA1");
-
-    /**
-     * If a request with this ID comes to the server, the server responds back with a single vertex picked from Modern
-     * graph. After some delay, server sends a Close WebSocket frame on the same connection.
-     */
-    public static final UUID SINGLE_VERTEX_DELAYED_CLOSE_CONNECTION_REQUEST_ID =
-            UUID.fromString("3cb39c94-9454-4398-8430-03485d08bdae");
-
-    public static final UUID FAILED_AFTER_DELAY_REQUEST_ID =
-            UUID.fromString("edf79c8b-1d32-4102-a5d2-a5feeca40864");
-    public static final UUID CLOSE_CONNECTION_REQUEST_ID =
-            UUID.fromString("0150143b-00f9-48a7-a268-28142d902e18");
-    public static final UUID CLOSE_CONNECTION_REQUEST_ID_2 =
-            UUID.fromString("3c4cf18a-c7f2-4dad-b9bf-5c701eb33000");
-    public static final UUID RESPONSE_CONTAINS_SERVER_ERROR_REQUEST_ID =
-            UUID.fromString("0d333b1d-6e91-4807-b915-50b9ad721d20");
-    /**
-     * If a request with this ID comes to the server, the server responds with the user agent (if any) that was captured
-     * during the web socket handshake.
-     */
-    public static final UUID USER_AGENT_REQUEST_ID =
-            UUID.fromString("20ad7bfb-4abf-d7f4-f9d3-9f1d55bee4ad");
-
-    /**
-     * Gremlin serializer used for serializing/deserializing the request/response. This should be same as client.
-     */
-    private static final GraphSONMessageSerializerV2d0 SERIALIZER = new GraphSONMessageSerializerV2d0();
-    private final static ByteBufAllocator allocator = UnpooledByteBufAllocator.DEFAULT;
-
-    @Override
-    public void postInit(ChannelPipeline pipeline) {
-        pipeline.addLast(new ClientTestConfigurableHandler());
-    }
-
-    /**
-     * Handler introduced in the server pipeline to configure expected response for test cases.
-     */
-    static class ClientTestConfigurableHandler extends MessageToMessageDecoder<BinaryWebSocketFrame> {
-        private String userAgent = "";
-        @Override
-        protected void decode(final ChannelHandlerContext ctx, final BinaryWebSocketFrame frame, final List<Object> objects)
-                throws Exception {
-            final ByteBuf messageBytes = frame.content();
-            final byte len = messageBytes.readByte();
-            if (len <= 0) {
-                objects.add(RequestMessage.INVALID);
-                return;
-            }
-
-            final ByteBuf contentTypeBytes = ctx.alloc().buffer(len);
-            try {
-                messageBytes.readBytes(contentTypeBytes);
-            } finally {
-                contentTypeBytes.release();
-            }
-            final RequestMessage msg = SERIALIZER.deserializeRequest(messageBytes.discardReadBytes());
-
-            if (msg.getRequestId().equals(SINGLE_VERTEX_DELAYED_CLOSE_CONNECTION_REQUEST_ID)) {
-                logger.info("sending vertex result frame");
-                ctx.channel().writeAndFlush(new TextWebSocketFrame(returnSingleVertexResponse(
-                        SINGLE_VERTEX_DELAYED_CLOSE_CONNECTION_REQUEST_ID)));
-                logger.info("waiting for 2 sec");
-                Thread.sleep(2000);
-                logger.info("sending close frame");
-                ctx.channel().writeAndFlush(new CloseWebSocketFrame());
-            } else if (msg.getRequestId().equals(SINGLE_VERTEX_REQUEST_ID)) {
-                logger.info("sending vertex result frame");
-                ctx.channel().writeAndFlush(new TextWebSocketFrame(returnSingleVertexResponse(SINGLE_VERTEX_REQUEST_ID)));
-            } else if (msg.getRequestId().equals(FAILED_AFTER_DELAY_REQUEST_ID)) {
-                logger.info("waiting for 2 sec");
-                Thread.sleep(1000);
-                final ResponseMessage responseMessage = ResponseMessage.build(msg)
-                        .code(ResponseStatusCode.SERVER_ERROR)
-                        .statusAttributeException(new RuntimeException()).create();
-                ctx.channel().writeAndFlush(new TextWebSocketFrame(SERIALIZER.serializeResponseAsString(responseMessage, allocator)));
-            } else if (msg.getRequestId().equals(CLOSE_CONNECTION_REQUEST_ID)) {
-                Thread.sleep(1000);
-                ctx.channel().writeAndFlush(new CloseWebSocketFrame());
-            } else if (msg.getRequestId().equals(RESPONSE_CONTAINS_SERVER_ERROR_REQUEST_ID)) {
-                Thread.sleep(1000);
-                ctx.channel().writeAndFlush(new CloseWebSocketFrame());
-            } else if (msg.getRequestId().equals(USER_AGENT_REQUEST_ID)) {
-                ctx.channel().writeAndFlush(new TextWebSocketFrame(returnSimpleStringResponse(USER_AGENT_REQUEST_ID, userAgent)));
-            } else {
-                try {
-                    Thread.sleep(Long.parseLong((String) msg.getArgs().get("gremlin")));
-                    ctx.channel().writeAndFlush(new TextWebSocketFrame(returnSingleVertexResponse(msg.getRequestId())));
-                } catch (NumberFormatException nfe) {
-                    // Ignore. Only return a vertex if the query was a long value.
-                }
-            }
-        }
-
-        private String returnSingleVertexResponse(final UUID requestID) throws SerializationException {
-            final TinkerGraph graph = TinkerFactory.createClassic();
-            final GraphTraversalSource g = graph.traversal();
-            final Vertex t = g.V().limit(1).next();
-
-            return SERIALIZER.serializeResponseAsString(ResponseMessage.build(requestID).result(t).create(), allocator);
-        }
-
-        /**
-         * Packages a string message into a ResponseMessage, serializes it, and returns the serialized string
-         * @throws SerializationException
-         */
-        private String returnSimpleStringResponse(final UUID requestID, String message) throws SerializationException {
-            return SERIALIZER.serializeResponseAsString(ResponseMessage.build(requestID).result(message).create(), allocator);
-        }
-
-        /**
-         * Captures and stores User-Agent if included in header
-         */
-        @Override
-        public void userEventTriggered(final ChannelHandlerContext ctx, final Object evt) {
-            if(evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
-                WebSocketServerProtocolHandler.HandshakeComplete handshake = (WebSocketServerProtocolHandler.HandshakeComplete) evt;
-                HttpHeaders requestHeaders = handshake.requestHeaders();
-                if(requestHeaders.contains(UserAgent.USER_AGENT_HEADER_NAME)) {
-                    userAgent = requestHeaders.get(UserAgent.USER_AGENT_HEADER_NAME);
-                }
-                else {
-                    ctx.fireUserEventTriggered(evt);
-                }
-            }
-        }
-    }
-}
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/TokensTest.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/TokensTest.java
index 4ab52fb..cbbb2d6 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/TokensTest.java
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/TokensTest.java
@@ -18,6 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.driver;
 
+import org.apache.tinkerpop.gremlin.util.Tokens;
 import org.junit.Test;
 
 import java.lang.reflect.Constructor;
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/WebSocketClientBehaviorIntegrateTest.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/WebSocketClientBehaviorIntegrateTest.java
index e9e781d..f3ba7b3 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/WebSocketClientBehaviorIntegrateTest.java
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/WebSocketClientBehaviorIntegrateTest.java
@@ -19,7 +19,10 @@
 package org.apache.tinkerpop.gremlin.driver;
 
 import nl.altindag.log.LogCaptor;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.AbstractWarningVerificationStrategy;
+import org.apache.tinkerpop.gremlin.socket.server.SimpleSocketServer;
+import org.apache.tinkerpop.gremlin.socket.server.SocketServerSettings;
+import org.apache.tinkerpop.gremlin.socket.server.TestChannelizers;
+import org.apache.tinkerpop.gremlin.socket.server.TestWSGremlinInitializer;
 import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Before;
@@ -30,10 +33,12 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.tinkerpop.gremlin.driver.exception.NoHostAvailableException;
-import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
+import org.apache.tinkerpop.gremlin.util.ser.Serializers;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.util.ExceptionHelper;
 
+import java.io.IOException;
+import java.nio.file.FileSystems;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
@@ -59,8 +64,15 @@
 
     private static LogCaptor logCaptor;
 
+    private final SocketServerSettings settings;
+
     private SimpleSocketServer server;
 
+    public WebSocketClientBehaviorIntegrateTest() throws IOException {
+        settings = SocketServerSettings.read(FileSystems.getDefault().getPath("..","gremlin-tools", "gremlin-socket-server", "conf", "test-ws-gremlin.yaml"));
+        settings.SERIALIZER = "GraphSONV2";
+    }
+
     @BeforeClass
     public static void setupLogCaptor() {
         logCaptor = LogCaptor.forRoot();
@@ -75,15 +87,15 @@
     public void setUp() throws InterruptedException {
         logCaptor.clearLogs();
 
-        server = new SimpleSocketServer();
+        server = new SimpleSocketServer(settings);
         if (name.getMethodName().equals("shouldAttemptHandshakeForLongerThanDefaultNettySslHandshakeTimeout") ||
                 name.getMethodName().equals("shouldPrintCorrectErrorForRegularWebSocketHandshakeTimeout")) {
             server.start(new TestChannelizers.TestWSNoOpInitializer());
         } else if (name.getMethodName().equals("shouldContinueRunningRemainingConnectionsIfServerThrottlesNewConnections") ||
                 name.getMethodName().equals("shouldReturnCorrectExceptionIfServerThrottlesNewConnectionsAndMaxWaitExceeded")) {
-            server.start(new TestChannelizers.TestConnectionThrottlingInitializer());
+            server.start(new TestChannelizers.TestConnectionThrottlingInitializer(settings));
         } else {
-            server.start(new TestWSGremlinInitializer());
+            server.start(new TestWSGremlinInitializer(settings));
         }
     }
 
@@ -98,7 +110,7 @@
      */
     @Test
     public void shouldIncludeUserAgentInHandshakeRequest() {
-        final Cluster cluster = Cluster.build("localhost").port(SimpleSocketServer.PORT)
+        final Cluster cluster = Cluster.build("localhost").port(settings.PORT)
                 .minConnectionPoolSize(1)
                 .maxConnectionPoolSize(1)
                 .serializer(Serializers.GRAPHSON_V2D0)
@@ -107,7 +119,7 @@
 
         // trigger the testing server to return captured user agent
         String returnedUserAgent = client.submit("1", RequestOptions.build()
-                        .overrideRequestId(TestWSGremlinInitializer.USER_AGENT_REQUEST_ID).create()).one().getString();
+                        .overrideRequestId(settings.USER_AGENT_REQUEST_ID).create()).one().getString();
         assertEquals(UserAgent.USER_AGENT, returnedUserAgent);
     }
 
@@ -116,7 +128,7 @@
      */
     @Test
     public void shouldNotIncludeUserAgentInHandshakeRequestIfDisabled() {
-        final Cluster cluster = Cluster.build("localhost").port(SimpleSocketServer.PORT)
+        final Cluster cluster = Cluster.build("localhost").port(settings.PORT)
                 .minConnectionPoolSize(1)
                 .maxConnectionPoolSize(1)
                 .serializer(Serializers.GRAPHSON_V2D0)
@@ -126,7 +138,7 @@
 
         // trigger the testing server to return captured user agent
         String returnedUserAgent = client.submit("1", RequestOptions.build()
-                .overrideRequestId(TestWSGremlinInitializer.USER_AGENT_REQUEST_ID).create()).one().getString();
+                .overrideRequestId(settings.USER_AGENT_REQUEST_ID).create()).one().getString();
         assertEquals("", returnedUserAgent);
     }
 
@@ -151,7 +163,7 @@
         // pool used just for the purpose of initializing the hosts).
         final Cluster cluster = Cluster.build("localhost").
                 addContactPoint("localhost").
-                addContactPoint("localhost").port(SimpleSocketServer.PORT).
+                addContactPoint("localhost").port(settings.PORT).
                 workerPoolSize(1).
                 minConnectionPoolSize(32).maxConnectionPoolSize(32).create();
 
@@ -188,7 +200,7 @@
      */
     @Test
     public void shouldRemoveConnectionFromPoolWhenServerClose_WithNoPendingRequests() throws InterruptedException {
-        final Cluster cluster = Cluster.build("localhost").port(SimpleSocketServer.PORT)
+        final Cluster cluster = Cluster.build("localhost").port(settings.PORT)
                 .minConnectionPoolSize(1)
                 .maxConnectionPoolSize(1)
                 .serializer(Serializers.GRAPHSON_V2D0)
@@ -207,7 +219,7 @@
 
         // trigger the testing server to send a WS close frame
         Vertex v = client.submit("1", RequestOptions.build()
-                .overrideRequestId(TestWSGremlinInitializer.SINGLE_VERTEX_DELAYED_CLOSE_CONNECTION_REQUEST_ID).create())
+                .overrideRequestId(settings.SINGLE_VERTEX_DELAYED_CLOSE_CONNECTION_REQUEST_ID).create())
                 .one().getVertex();
 
         assertNotNull(v);
@@ -224,7 +236,7 @@
 
         // assert sanity after connection replacement
         v = client.submit("1",
-                RequestOptions.build().overrideRequestId(TestWSGremlinInitializer.SINGLE_VERTEX_REQUEST_ID).create())
+                RequestOptions.build().overrideRequestId(settings.SINGLE_VERTEX_REQUEST_ID).create())
                 .one().getVertex();
         assertNotNull(v);
     }
@@ -235,7 +247,7 @@
      */
     @Test
     public void shouldRemoveConnectionFromPoolWhenServerClose_WithPendingRequests() throws InterruptedException, ExecutionException {
-        final Cluster cluster = Cluster.build("localhost").port(SimpleSocketServer.PORT)
+        final Cluster cluster = Cluster.build("localhost").port(settings.PORT)
                 .minConnectionPoolSize(1)
                 .maxConnectionPoolSize(1)
                 .serializer(Serializers.GRAPHSON_V2D0)
@@ -252,9 +264,9 @@
 
         // Send two requests in flight. Both should error out.
         final CompletableFuture<ResultSet> req1 = client.submitAsync("1", RequestOptions.build()
-                .overrideRequestId(TestWSGremlinInitializer.CLOSE_CONNECTION_REQUEST_ID).create());
+                .overrideRequestId(settings.CLOSE_CONNECTION_REQUEST_ID).create());
         final CompletableFuture<ResultSet> req2 = client.submitAsync("1", RequestOptions.build()
-                .overrideRequestId(TestWSGremlinInitializer.CLOSE_CONNECTION_REQUEST_ID_2).create());
+                .overrideRequestId(settings.CLOSE_CONNECTION_REQUEST_ID_2).create());
 
 
         // assert both are sent on same connection
@@ -272,7 +284,7 @@
 
         // assert sanity after connection replacement
         final Vertex v = client.submit("1",
-                RequestOptions.build().overrideRequestId(TestWSGremlinInitializer.SINGLE_VERTEX_REQUEST_ID).create())
+                RequestOptions.build().overrideRequestId(settings.SINGLE_VERTEX_REQUEST_ID).create())
                 .one().getVertex();
         assertNotNull(v);
     }
@@ -283,7 +295,7 @@
      */
     @Test
     public void shouldNotCreateReplacementConnectionWhenClientClosesConnection() throws ExecutionException, InterruptedException {
-        final Cluster cluster = Cluster.build("localhost").port(SimpleSocketServer.PORT)
+        final Cluster cluster = Cluster.build("localhost").port(settings.PORT)
                 .minConnectionPoolSize(1)
                 .maxConnectionPoolSize(1)
                 .serializer(Serializers.GRAPHSON_V2D0)
@@ -320,7 +332,7 @@
      */
     @Test
     public void shouldAttemptHandshakeForLongerThanDefaultNettySslHandshakeTimeout() {
-        final Cluster cluster = Cluster.build("localhost").port(SimpleSocketServer.PORT)
+        final Cluster cluster = Cluster.build("localhost").port(settings.PORT)
                 .minConnectionPoolSize(1)
                 .maxConnectionPoolSize(1)
                 .connectionSetupTimeoutMillis(20000) // needs to be larger than 10000ms.
@@ -351,7 +363,7 @@
      */
     @Test
     public void shouldPrintCorrectErrorForRegularWebSocketHandshakeTimeout() throws InterruptedException {
-        final Cluster cluster = Cluster.build("localhost").port(SimpleSocketServer.PORT)
+        final Cluster cluster = Cluster.build("localhost").port(settings.PORT)
                 .minConnectionPoolSize(1)
                 .maxConnectionPoolSize(1)
                 .connectionSetupTimeoutMillis(120)
@@ -380,7 +392,7 @@
      */
     @Test
     public void shouldContinueRunningRemainingConnectionsIfServerThrottlesNewConnections() throws ExecutionException, InterruptedException, TimeoutException {
-        final Cluster cluster = Cluster.build("localhost").port(SimpleSocketServer.PORT)
+        final Cluster cluster = Cluster.build("localhost").port(settings.PORT)
                 .minConnectionPoolSize(1)
                 .maxConnectionPoolSize(5)
                 .maxWaitForConnection(15000) // large value ensures that request will eventually find a connection.
@@ -413,7 +425,7 @@
      */
     @Test
     public void shouldReturnCorrectExceptionIfServerThrottlesNewConnectionsAndMaxWaitExceeded() {
-        final Cluster cluster = Cluster.build("localhost").port(SimpleSocketServer.PORT)
+        final Cluster cluster = Cluster.build("localhost").port(settings.PORT)
                 .minConnectionPoolSize(1)
                 .maxConnectionPoolSize(5)
                 .maxWaitForConnection(250) // small value ensures that requests will return TimeoutException.
@@ -445,7 +457,7 @@
      */
     @Test
     public void shouldContinueRunningIfServerGoesDownTemporarily() throws InterruptedException {
-        final Cluster cluster = Cluster.build("localhost").port(SimpleSocketServer.PORT)
+        final Cluster cluster = Cluster.build("localhost").port(settings.PORT)
                 .minConnectionPoolSize(1)
                 .serializer(Serializers.GRAPHSON_V2D0)
                 .create();
@@ -457,8 +469,8 @@
         scheduledPool.schedule(() -> {
             try {
                 server.stopSync();
-                server = new SimpleSocketServer();
-                server.start(new TestWSGremlinInitializer());
+                server = new SimpleSocketServer(settings);
+                server.start(new TestWSGremlinInitializer(settings));
                 synchronized (lock) {
                     lock.notify();
                 }
@@ -483,7 +495,7 @@
      */
     @Test
     public void shouldReturnCorrectExceptionIfServerGoesDown() throws InterruptedException {
-        final Cluster cluster = Cluster.build("localhost").port(SimpleSocketServer.PORT)
+        final Cluster cluster = Cluster.build("localhost").port(settings.PORT)
                 .minConnectionPoolSize(1)
                 .maxWaitForConnection(500)
                 .connectionSetupTimeoutMillis(100)
@@ -505,4 +517,27 @@
 
         cluster.close();
     }
+
+    /**
+     * Tests that client is correctly sending all overridable per request settings (requestId, batchSize,
+     * evaluationTimeout, and userAgent) to the server.
+     */
+    @Test
+    public void shouldSendPerRequestSettingsToServer() {
+        final Cluster cluster = Cluster.build("localhost").port(settings.PORT)
+                .minConnectionPoolSize(1)
+                .maxConnectionPoolSize(1)
+                .serializer(Serializers.GRAPHSON_V2D0)
+                .create();
+        final Client.ClusteredClient client = cluster.connect();
+
+        // trigger the testing server to return captured request settings
+        String response = client.submit("1", RequestOptions.build()
+                .overrideRequestId(settings.PER_REQUEST_SETTINGS_REQUEST_ID)
+                .timeout(1234).userAgent("helloWorld").batchSize(12).create()).one().getString();
+
+        String expectedResponse = String.format("requestId=%s evaluationTimeout=%d, batchSize=%d, userAgent=%s",
+                settings.PER_REQUEST_SETTINGS_REQUEST_ID, 1234, 12, "helloWorld");
+        assertEquals(expectedResponse, response);
+    }
 }
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 7101133..dcaa2d2 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
@@ -19,7 +19,7 @@
 package org.apache.tinkerpop.gremlin.driver.remote;
 
 import org.apache.tinkerpop.gremlin.driver.RequestOptions;
-import org.apache.tinkerpop.gremlin.driver.Tokens;
+import org.apache.tinkerpop.gremlin.util.Tokens;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
 import org.junit.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
deleted file mode 100644
index 83f3fa3..0000000
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryReaderWriterRoundTripTest.java
+++ /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.
- */
-package org.apache.tinkerpop.gremlin.driver.ser.binary;
-
-import io.netty.buffer.ByteBufAllocator;
-import org.apache.tinkerpop.gremlin.driver.ser.AbstractRoundTripTest;
-import org.apache.tinkerpop.gremlin.driver.ser.NettyBufferFactory;
-import org.apache.tinkerpop.gremlin.process.computer.Computer;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.VertexProgramStrategy;
-import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
-import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
-import org.apache.tinkerpop.gremlin.process.traversal.Operator;
-import org.apache.tinkerpop.gremlin.process.traversal.Order;
-import org.apache.tinkerpop.gremlin.process.traversal.P;
-import org.apache.tinkerpop.gremlin.process.traversal.Pick;
-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.TextP;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.TraversalStrategyProxy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalMetrics;
-import org.apache.tinkerpop.gremlin.process.traversal.util.Metrics;
-import org.apache.tinkerpop.gremlin.process.traversal.util.MutableMetrics;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
-import org.apache.tinkerpop.gremlin.structure.Column;
-import org.apache.tinkerpop.gremlin.structure.Direction;
-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.io.Buffer;
-import org.apache.tinkerpop.gremlin.structure.io.IoTest;
-import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader;
-import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter;
-import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceEdge;
-import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceProperty;
-import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceVertex;
-import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceVertexProperty;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
-import org.apache.tinkerpop.gremlin.util.function.Lambda;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.net.InetAddress;
-import java.nio.ByteBuffer;
-import java.sql.Timestamp;
-import java.text.DateFormat;
-import java.time.Duration;
-import java.time.Instant;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
-import java.time.MonthDay;
-import java.time.OffsetDateTime;
-import java.time.OffsetTime;
-import java.time.Period;
-import java.time.Year;
-import java.time.YearMonth;
-import java.time.ZoneOffset;
-import java.time.ZonedDateTime;
-import java.util.*;
-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.hamcrest.MatcherAssert.assertThat;
-
-public class GraphBinaryReaderWriterRoundTripTest extends AbstractRoundTripTest {
-    private final GraphBinaryWriter writer = new GraphBinaryWriter();
-    private final GraphBinaryReader reader = new GraphBinaryReader();
-    private final ByteBufAllocator allocator = ByteBufAllocator.DEFAULT;
-    private static NettyBufferFactory bufferFactory = new NettyBufferFactory();
-
-    @Test
-    public void shouldWriteAndRead() throws Exception {
-        // Test it multiple times as the type registry might change its internal state
-        for (int i = 0; i < 5; i++) {
-            final Buffer buffer = bufferFactory.create(allocator.buffer());
-            writer.write(value, buffer);
-            buffer.readerIndex(0);
-            final Object result = reader.read(buffer);
-
-            Optional.ofNullable(assertion).orElse((Consumer) r -> assertEquals(value, r)).accept(result);
-        }
-    }
-}
diff --git a/gremlin-go/docker-compose.yml b/gremlin-go/docker-compose.yml
index 3ca3045..085b5a4 100644
--- a/gremlin-go/docker-compose.yml
+++ b/gremlin-go/docker-compose.yml
@@ -42,6 +42,8 @@
       timeout: 10s
       retries: 30
       start_period: 30s
+    depends_on:
+      - gremlin-socket-server
 
   gremlin-go-integration-tests:
     container_name: gremlin-go-integration-tests
@@ -50,6 +52,7 @@
       - .:/go_app
       - ../gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features:/gremlin-test
       - ../docker/gremlin-test-server:/go_app/gremlin-test-server
+      - ../gremlin-tools/gremlin-socket-server/conf:/go_app/gremlin-socket-server/conf/
     environment:
       - CUCUMBER_FEATURE_FOLDER=/gremlin-test
       - GREMLIN_SERVER_URL=ws://gremlin-server-test:45940/gremlin
@@ -58,6 +61,8 @@
       - RUN_INTEGRATION_WITH_ALIAS_TESTS=true
       - RUN_BASIC_AUTH_INTEGRATION_TESTS=true
       - TEST_TRANSACTIONS=true
+      - GREMLIN_SOCKET_SERVER_URL=ws://gremlin-socket-server-go
+      - GREMLIN_SOCKET_SERVER_CONFIG_PATH=/go_app/gremlin-socket-server/conf/test-ws-gremlin.yaml
     working_dir: /go_app
     command: >
       bash -c "go install github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@latest
@@ -65,3 +70,9 @@
     depends_on:
       gremlin-server-test:
         condition: service_healthy
+
+  gremlin-socket-server:
+    container_name: gremlin-socket-server-go
+    image: tinkerpop/gremlin-socket-server:${GREMLIN_SERVER}
+    ports:
+      - "45943:45943"
diff --git a/gremlin-go/driver/anonymousTraversal.go b/gremlin-go/driver/anonymousTraversal.go
index a9475c6..37fda56 100644
--- a/gremlin-go/driver/anonymousTraversal.go
+++ b/gremlin-go/driver/anonymousTraversal.go
@@ -45,6 +45,8 @@
 type AnonymousTraversal interface {
 	// T__ creates an empty GraphTraversal.
 	T__(args ...interface{}) *GraphTraversal
+	// E adds the e step to the GraphTraversal.
+	E(args ...interface{}) *GraphTraversal
 	// V adds the v step to the GraphTraversal.
 	V(args ...interface{}) *GraphTraversal
 	// AddE adds the addE step to the GraphTraversal.
@@ -278,6 +280,11 @@
 	return anonymousTraversal.Inject(args...)
 }
 
+// E adds the e step to the GraphTraversal.
+func (anonymousTraversal *anonymousTraversal) E(args ...interface{}) *GraphTraversal {
+	return anonymousTraversal.graphTraversal().E(args...)
+}
+
 // V adds the v step to the GraphTraversal.
 func (anonymousTraversal *anonymousTraversal) V(args ...interface{}) *GraphTraversal {
 	return anonymousTraversal.graphTraversal().V(args...)
diff --git a/gremlin-go/driver/client_test.go b/gremlin-go/driver/client_test.go
index 7413bf5..801ab28 100644
--- a/gremlin-go/driver/client_test.go
+++ b/gremlin-go/driver/client_test.go
@@ -21,9 +21,14 @@
 
 import (
 	"crypto/tls"
+	"fmt"
+	"log"
+	"os"
 	"testing"
 
+	"github.com/google/uuid"
 	"github.com/stretchr/testify/assert"
+	"gopkg.in/yaml.v3"
 )
 
 func TestClient(t *testing.T) {
@@ -33,25 +38,6 @@
 	testNoAuthAuthInfo := &AuthInfo{}
 	testNoAuthTlsConfig := &tls.Config{}
 
-	t.Run("Test client.Submit()", func(t *testing.T) {
-		skipTestsIfNotEnabled(t, integrationTestSuiteName, testNoAuthEnable)
-		client, err := NewClient(testNoAuthUrl,
-			func(settings *ClientSettings) {
-				settings.TlsConfig = testNoAuthTlsConfig
-				settings.AuthInfo = testNoAuthAuthInfo
-			})
-		defer client.Close()
-		assert.NoError(t, err)
-		assert.NotNil(t, client)
-		resultSet, err := client.Submit("g.V().count()")
-		assert.NoError(t, err)
-		assert.NotNil(t, resultSet)
-		result, ok, err := resultSet.One()
-		assert.NoError(t, err)
-		assert.True(t, ok)
-		assert.NotNil(t, result)
-	})
-
 	t.Run("Test client.SubmitWithOptions()", func(t *testing.T) {
 		skipTestsIfNotEnabled(t, integrationTestSuiteName, testNoAuthEnable)
 		client, err := NewClient(testNoAuthUrl,
@@ -59,9 +45,10 @@
 				settings.TlsConfig = testNoAuthTlsConfig
 				settings.AuthInfo = testNoAuthAuthInfo
 			})
-		defer client.Close()
 		assert.NoError(t, err)
 		assert.NotNil(t, client)
+		defer client.Close()
+
 		resultSet, err := client.SubmitWithOptions("g.V().count()", *new(RequestOptions))
 		assert.NoError(t, err)
 		assert.NotNil(t, resultSet)
@@ -90,4 +77,330 @@
 		assert.True(t, pool.isClosed)
 		assert.Equal(t, closed, pool.connections[0].state)
 	})
+
+	t.Run("Test client.Submit()", func(t *testing.T) {
+		skipTestsIfNotEnabled(t, integrationTestSuiteName, testNoAuthEnable)
+		client, err := NewClient(testNoAuthUrl,
+			func(settings *ClientSettings) {
+				settings.TlsConfig = testNoAuthTlsConfig
+				settings.AuthInfo = testNoAuthAuthInfo
+				settings.TraversalSource = testServerModernGraphAlias
+			})
+		assert.NoError(t, err)
+		assert.NotNil(t, client)
+		defer client.Close()
+
+		resultSet, err := client.Submit("g.V(1)")
+		assert.NoError(t, err)
+		assert.NotNil(t, resultSet)
+
+		result, ok, err := resultSet.One()
+		assert.NoError(t, err)
+		assert.True(t, ok)
+
+		AssertMarkoVertexWithProperties(t, result)
+	})
+
+	t.Run("Test client.submit() with materializeProperties", func(t *testing.T) {
+		skipTestsIfNotEnabled(t, integrationTestSuiteName, testNoAuthEnable)
+		client, err := NewClient(testNoAuthUrl,
+			func(settings *ClientSettings) {
+				settings.TlsConfig = testNoAuthTlsConfig
+				settings.AuthInfo = testNoAuthAuthInfo
+				settings.TraversalSource = testServerModernGraphAlias
+			})
+
+		assert.NoError(t, err)
+		assert.NotNil(t, client)
+		defer client.Close()
+
+		resultSet, err := client.Submit("g.with('materializeProperties', 'tokens').V(1)")
+		assert.NoError(t, err)
+		assert.NotNil(t, resultSet)
+		result, ok, err := resultSet.One()
+		assert.NoError(t, err)
+		assert.True(t, ok)
+
+		AssertMarkoVertexWithoutProperties(t, result)
+	})
+
+	t.Run("Test deserialization of VertexProperty with properties", func(t *testing.T) {
+		skipTestsIfNotEnabled(t, integrationTestSuiteName, testNoAuthEnable)
+		client, err := NewClient(testNoAuthUrl,
+			func(settings *ClientSettings) {
+				settings.TlsConfig = testNoAuthTlsConfig
+				settings.AuthInfo = testNoAuthAuthInfo
+				settings.TraversalSource = testServerCrewGraphAlias
+			})
+
+		assert.NoError(t, err)
+		assert.NotNil(t, client)
+		defer client.Close()
+
+		resultSet, err := client.Submit("g.V(7)")
+		assert.NoError(t, err)
+		assert.NotNil(t, resultSet)
+		result, ok, err := resultSet.One()
+		assert.NoError(t, err)
+		assert.True(t, ok)
+
+		AssertVertexPropertiesWithProperties(t, result)
+	})
+}
+
+func AssertVertexPropertiesWithProperties(t *testing.T, result *Result) {
+	assert.NotNil(t, result)
+
+	vertex, err := result.GetVertex()
+	assert.NoError(t, err)
+	assert.NotNil(t, vertex)
+
+	properties, ok := vertex.Properties.([]interface{})
+	assert.True(t, ok)
+	assert.Equal(t, 4, len(properties))
+
+	property, ok := properties[1].(*VertexProperty)
+	assert.True(t, ok)
+	assert.NotNil(t, property)
+	assert.Equal(t, "centreville", property.Value)
+	vertexPropertyProperties := property.Properties.([]interface{})
+	assert.Equal(t, 2, len(vertexPropertyProperties))
+	assert.Equal(t, "startTime", (vertexPropertyProperties[0].(*Property)).Key)
+	assert.Equal(t, int32(1990), (vertexPropertyProperties[0].(*Property)).Value)
+	assert.Equal(t, "endTime", (vertexPropertyProperties[1].(*Property)).Key)
+	assert.Equal(t, int32(2000), (vertexPropertyProperties[1].(*Property)).Value)
+}
+
+func AssertMarkoVertexWithProperties(t *testing.T, result *Result) {
+	assert.NotNil(t, result)
+
+	vertex, err := result.GetVertex()
+	assert.NoError(t, err)
+	assert.NotNil(t, vertex)
+
+	properties, ok := vertex.Properties.([]interface{})
+	assert.True(t, ok)
+	assert.Equal(t, 2, len(properties))
+
+	property, ok := properties[0].(*VertexProperty)
+	assert.True(t, ok)
+	assert.NotNil(t, property)
+	assert.Equal(t, "name", property.Label)
+	assert.Equal(t, "marko", property.Value)
+
+	property, ok = properties[1].(*VertexProperty)
+	assert.True(t, ok)
+	assert.NotNil(t, property)
+	assert.Equal(t, "age", property.Label)
+	assert.Equal(t, int32(29), property.Value)
+}
+
+func AssertMarkoVertexWithoutProperties(t *testing.T, result *Result) {
+	assert.NotNil(t, result)
+
+	vertex, err := result.GetVertex()
+	assert.NoError(t, err)
+	assert.NotNil(t, vertex)
+
+	properties, ok := vertex.Properties.([]interface{})
+	assert.True(t, ok)
+	assert.Equal(t, 0, len(properties))
+}
+
+// Client is used to connect and interact with a Gremlin-supported server.
+type SocketServerSettings struct {
+	PORT int `yaml:"PORT"`
+	/**
+	 * Configures which serializer will be used. Ex: "GraphBinaryV1" or "GraphSONV2"
+	 */
+	SERIALIZER string `yaml:"SERIALIZER"`
+	/**
+	 * If a request with this ID comes to the server, the server responds back with a single vertex picked from Modern
+	 * graph.
+	 */
+	SINGLE_VERTEX_REQUEST_ID uuid.UUID `yaml:"SINGLE_VERTEX_REQUEST_ID"`
+	/**
+	 * If a request with this ID comes to the server, the server responds back with a single vertex picked from Modern
+	 * graph. After a 2 second delay, server sends a Close WebSocket frame on the same connection.
+	 */
+	SINGLE_VERTEX_DELAYED_CLOSE_CONNECTION_REQUEST_ID uuid.UUID `yaml:"SINGLE_VERTEX_DELAYED_CLOSE_CONNECTION_REQUEST_ID"`
+	/**
+	 * Server waits for 1 second, then responds with a 500 error status code
+	 */
+	FAILED_AFTER_DELAY_REQUEST_ID uuid.UUID `yaml:"FAILED_AFTER_DELAY_REQUEST_ID"`
+	/**
+	 * Server waits for 1 second then responds with a close web socket frame
+	 */
+	CLOSE_CONNECTION_REQUEST_ID uuid.UUID `yaml:"CLOSE_CONNECTION_REQUEST_ID"`
+	/**
+	 * Same as CLOSE_CONNECTION_REQUEST_ID
+	 */
+	CLOSE_CONNECTION_REQUEST_ID_2 uuid.UUID `yaml:"CLOSE_CONNECTION_REQUEST_ID_2"`
+	/**
+	 * If a request with this ID comes to the server, the server responds with the user agent (if any) that was captured
+	 * during the web socket handshake.
+	 */
+	USER_AGENT_REQUEST_ID uuid.UUID `yaml:"USER_AGENT_REQUEST_ID"`
+	/**
+	 * If a request with this ID comes to the server, the server responds with a string containing all overridden
+	 * per request settings from the request message. String will be of the form
+	 * "requestId=19436d9e-f8fc-4b67-8a76-deec60918424 evaluationTimeout=1234, batchSize=12, userAgent=testUserAgent"
+	 */
+	PER_REQUEST_SETTINGS_REQUEST_ID uuid.UUID `yaml:"PER_REQUEST_SETTINGS_REQUEST_ID"`
+}
+
+func FromYaml(path string) *SocketServerSettings {
+	socketServerSettings := new(SocketServerSettings)
+	f, err := os.ReadFile(path)
+	if err != nil {
+		log.Fatal(err)
+	}
+	if err := yaml.Unmarshal(f, socketServerSettings); err != nil {
+		log.Fatal(err)
+	}
+	return socketServerSettings
+}
+
+func TestClientAgainstSocketServer(t *testing.T) {
+	// Integration test variables.
+	testNoAuthEnable := getEnvOrDefaultBool("RUN_INTEGRATION_TESTS", true)
+	settings := FromYaml(getEnvOrDefaultString("GREMLIN_SOCKET_SERVER_CONFIG_PATH", "../../gremlin-tools/gremlin-socket-server/conf/test-ws-gremlin.yaml"))
+	testSocketServerUrl := getEnvOrDefaultString("GREMLIN_SOCKET_SERVER_URL", "ws://localhost")
+	testSocketServerUrl = fmt.Sprintf("%s:%v/gremlin", testSocketServerUrl, settings.PORT)
+
+	/**
+	 * Note: This test does not demonstrate anything useful other than the ability to connect to and
+	 * use gremlin-socket-server. Currently, implementing more useful tests are blocked by TINKERPOP-2845.
+	 * This test can be safely removed once more interesting tests have been added which utilize
+	 * gremlin-socket-server.
+	 */
+	t.Run("Should get single vertex response from gremlin socket server", func(t *testing.T) {
+		skipTestsIfNotEnabled(t, integrationTestSuiteName, testNoAuthEnable)
+		client, err := NewClient(testSocketServerUrl)
+		assert.Nil(t, err)
+		assert.NotNil(t, client)
+		defer client.Close()
+		resultSet, err := client.SubmitWithOptions("1", new(RequestOptionsBuilder).
+			SetRequestId(settings.SINGLE_VERTEX_REQUEST_ID).Create())
+		assert.Nil(t, err)
+		assert.NotNil(t, resultSet)
+		result, ok, err := resultSet.One()
+		assert.Nil(t, err)
+		assert.True(t, ok)
+		assert.NotNil(t, result)
+	})
+
+	/**
+	 * Tests that client is correctly sending user agent during web socket handshake by having the server return
+	 * the captured user agent.
+	 */
+	t.Run("Should include user agent in handshake request", func(t *testing.T) {
+		skipTestsIfNotEnabled(t, integrationTestSuiteName, testNoAuthEnable)
+		client, err := NewClient(testSocketServerUrl)
+		assert.Nil(t, err)
+		assert.NotNil(t, client)
+		defer client.Close()
+
+		resultSet, err := client.SubmitWithOptions("1", new(RequestOptionsBuilder).
+			SetRequestId(settings.USER_AGENT_REQUEST_ID).Create())
+		assert.Nil(t, err)
+		assert.NotNil(t, resultSet)
+
+		result, ok, err := resultSet.One()
+		assert.Nil(t, err)
+		assert.True(t, ok)
+		assert.NotNil(t, result)
+
+		userAgentResponse := result.GetString()
+		assert.Equal(t, userAgent, userAgentResponse)
+	})
+
+	/**
+	 * Tests that no user agent (other than the default one provided by gorilla) is sent to server when
+	 * that behaviour is disabled.
+	 */
+	t.Run("Should not include user agent in handshake request if disabled", func(t *testing.T) {
+		skipTestsIfNotEnabled(t, integrationTestSuiteName, testNoAuthEnable)
+		client, err := NewClient(testSocketServerUrl,
+			func(settings *ClientSettings) {
+				settings.EnableUserAgentOnConnect = false
+			})
+		assert.Nil(t, err)
+		assert.NotNil(t, client)
+		defer client.Close()
+
+		resultSet, err := client.SubmitWithOptions("1", new(RequestOptionsBuilder).
+			SetRequestId(settings.USER_AGENT_REQUEST_ID).Create())
+		assert.Nil(t, err)
+		assert.NotNil(t, resultSet)
+
+		result, ok, err := resultSet.One()
+		assert.Nil(t, err)
+		assert.True(t, ok)
+		assert.NotNil(t, result)
+
+		userAgentResponse := result.GetString()
+		//If the gremlin user agent is disabled, the underlying web socket library reverts to sending its default user agent
+		//during connection requests.
+		assert.Contains(t, userAgentResponse, "Go-http-client/")
+	})
+
+	/**
+	 * Tests that client is correctly sending all overridable per request settings (requestId, batchSize,
+	 * evaluationTimeout, and userAgent) to the server.
+	 */
+	t.Run("Should Send Per Request Settings To Server", func(t *testing.T) {
+		skipTestsIfNotEnabled(t, integrationTestSuiteName, testNoAuthEnable)
+		client, err := NewClient(testSocketServerUrl)
+		assert.Nil(t, err)
+		assert.NotNil(t, client)
+		defer client.Close()
+
+		resultSet, err := client.SubmitWithOptions("1", new(RequestOptionsBuilder).
+			SetRequestId(settings.PER_REQUEST_SETTINGS_REQUEST_ID).
+			SetEvaluationTimeout(1234).
+			SetBatchSize(12).
+			SetUserAgent("helloWorld").
+			Create())
+		assert.Nil(t, err)
+		assert.NotNil(t, resultSet)
+		result, ok, err := resultSet.One()
+		assert.Nil(t, err)
+		assert.True(t, ok)
+		expectedResult := fmt.Sprintf("requestId=%v evaluationTimeout=%v, batchSize=%v, userAgent=%v",
+			settings.PER_REQUEST_SETTINGS_REQUEST_ID, 1234, 12, "helloWorld")
+		assert.Equal(t, expectedResult, result.Data)
+	})
+
+	/**
+	 * Note: This test currently fails due to race condition check in go test and is only included for demonstration
+	 * purposes. See https://issues.apache.org/jira/browse/TINKERPOP-2845.
+	 * This test should be uncommented with the resolution of TINKERPOP-2845
+	 */
+	/*
+		t.Run("Should try create new connection if closed by server", func(t *testing.T) {
+			skipTestsIfNotEnabled(t, integrationTestSuiteName, testNoAuthEnable)
+			client, err := NewClient(testSocketServerUrl)
+			defer client.Close()
+			assert.Nil(t, err)
+			assert.NotNil(t, client)
+			resultSet, err := client.SubmitWithOptions("1", new(RequestOptionsBuilder).
+				SetRequestId(settings.CLOSE_CONNECTION_REQUEST_ID).Create())
+			assert.Nil(t, err)
+			assert.NotNil(t, resultSet)
+
+			result, ok, err := resultSet.One()
+
+			assert.EqualError(t, err, "websocket: close 1005 (no status)")
+
+			resultSet, err = client.SubmitWithOptions("1", new(RequestOptionsBuilder).
+				SetRequestId(settings.SINGLE_VERTEX_REQUEST_ID).Create())
+			assert.Nil(t, err)
+			assert.NotNil(t, resultSet)
+			result, ok, err = resultSet.One()
+			assert.Nil(t, err)
+			assert.True(t, ok)
+			assert.NotNil(t, result)
+		})
+	*/
 }
diff --git a/gremlin-go/driver/connection_test.go b/gremlin-go/driver/connection_test.go
index 0e3fb2d..92dce79 100644
--- a/gremlin-go/driver/connection_test.go
+++ b/gremlin-go/driver/connection_test.go
@@ -45,6 +45,7 @@
 const invalidHostValidPortValidPath = "ws://invalidhost:8182/gremlin"
 const testServerModernGraphAlias = "gmodern"
 const testServerGraphAlias = "gimmutable"
+const testServerCrewGraphAlias = "gcrew"
 const manualTestSuiteName = "manual"
 const nonRoutableIPForConnectionTimeout = "ws://10.255.255.1/"
 
@@ -1191,4 +1192,42 @@
 			assert.Equal(t, <-gotErrs[i] == nil, tt.nilErr, tt.msg)
 		}
 	})
+
+	t.Run("Get all properties when materializeProperties is all", func(t *testing.T) {
+		skipTestsIfNotEnabled(t, integrationTestSuiteName, testNoAuthEnable)
+
+		g := getModernGraph(t, testNoAuthUrl, &AuthInfo{}, &tls.Config{})
+		defer g.remoteConnection.Close()
+
+		// vertex contains 2 properties, name and age
+		r, err := g.With("materializeProperties", MaterializeProperties.All).V().Has("person", "name", "marko").Next()
+		assert.Nil(t, err)
+
+		AssertMarkoVertexWithProperties(t, r)
+	})
+
+	t.Run("Skip properties when materializeProperties is tokens", func(t *testing.T) {
+		skipTestsIfNotEnabled(t, integrationTestSuiteName, testNoAuthEnable)
+
+		g := getModernGraph(t, testNoAuthUrl, &AuthInfo{}, &tls.Config{})
+		defer g.remoteConnection.Close()
+
+		// vertex contains 2 properties, name and age
+		r, err := g.With("materializeProperties", MaterializeProperties.Tokens).V().Has("person", "name", "marko").Next()
+		assert.Nil(t, err)
+
+		AssertMarkoVertexWithoutProperties(t, r)
+	})
+
+	t.Run("Get all properties when no materializeProperties", func(t *testing.T) {
+		skipTestsIfNotEnabled(t, integrationTestSuiteName, testNoAuthEnable)
+
+		g := getModernGraph(t, testNoAuthUrl, &AuthInfo{}, &tls.Config{})
+		defer g.remoteConnection.Close()
+
+		r, err := g.V().Has("person", "name", "marko").Next()
+		assert.Nil(t, err)
+
+		AssertMarkoVertexWithProperties(t, r)
+	})
 }
diff --git a/gremlin-go/driver/cucumber/gremlin.go b/gremlin-go/driver/cucumber/gremlin.go
index 1444206..bfa60c2 100644
--- a/gremlin-go/driver/cucumber/gremlin.go
+++ b/gremlin-go/driver/cucumber/gremlin.go
@@ -475,6 +475,12 @@
     "g_E_sampleX1X_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().Sample(1).Count()}}, 
     "g_V_sampleX1X_byXageX_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Sample(1).By("age").Count()}}, 
     "g_V_order_byXnoX_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Order().By("no").Count()}}, 
+    "g_V_EX11X": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().E(p["eid11"])}}, 
+    "g_EX11X_E": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E(p["eid11"]).E()}}, 
+    "g_V_EXnullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().E(nil)}}, 
+    "g_V_EXlistXnullXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().E(p["xx1"])}}, 
+    "g_injectX1X_EX11_nullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(1).E(p["eid11"], nil)}}, 
+    "g_injectX1X_coalesceXEX_hasLabelXtestsX_addEXtestsX_from_V_hasXnameX_XjoshXX_toXV_hasXnameX_XvadasXXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.AddV("person").Property("name", "josh").AddV("person").Property("name", "vadas")}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(1).Coalesce(gremlingo.T__.E().HasLabel("tests"), gremlingo.T__.AddE("tests").From(gremlingo.T__.V().Has("name", "josh")).To(gremlingo.T__.V().Has("name", "vadas")))}, func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.E().HasLabel("tests")}}, 
     "g_VX1X_properties_element": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V(p["v2"]).Properties().Element().Limit(1)}}, 
     "g_V_properties_element": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Properties().Element()}}, 
     "g_V_propertiesXageX_element": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Properties("age").Element()}}, 
diff --git a/gremlin-go/driver/graph.go b/gremlin-go/driver/graph.go
index 5fe7125..ade4c32 100644
--- a/gremlin-go/driver/graph.go
+++ b/gremlin-go/driver/graph.go
@@ -34,6 +34,7 @@
 type Element struct {
 	Id    interface{}
 	Label string
+	Properties interface{}
 }
 
 // Vertex contains a single Vertex which has a Label and an Id.
diff --git a/gremlin-go/driver/graphBinary.go b/gremlin-go/driver/graphBinary.go
index 5d4dfd8..b729f5a 100644
--- a/gremlin-go/driver/graphBinary.go
+++ b/gremlin-go/driver/graphBinary.go
@@ -23,11 +23,12 @@
 	"bytes"
 	"encoding/binary"
 	"fmt"
-	"github.com/google/uuid"
 	"math"
 	"math/big"
 	"reflect"
 	"time"
+
+	"github.com/google/uuid"
 )
 
 // Version 1.0
@@ -433,7 +434,7 @@
 	return buffer.Bytes(), nil
 }
 
-//Format: {Key}{Value}{parent}
+// Format: {Key}{Value}{parent}
 func propertyWriter(value interface{}, buffer *bytes.Buffer, typeSerializer *graphBinaryTypeSerializer) ([]byte, error) {
 	v := value.(*Property)
 
@@ -452,7 +453,7 @@
 	return buffer.Bytes(), nil
 }
 
-//Format: {Id}{Label}{Value}{parent}{properties}
+// Format: {Id}{Label}{Value}{parent}{properties}
 func vertexPropertyWriter(value interface{}, buffer *bytes.Buffer, typeSerializer *graphBinaryTypeSerializer) ([]byte, error) {
 	vp := value.(*VertexProperty)
 	_, err := typeSerializer.write(vp.Id, buffer)
@@ -475,7 +476,7 @@
 	return buffer.Bytes(), nil
 }
 
-//Format: {Labels}{Objects}
+// Format: {Labels}{Objects}
 func pathWriter(value interface{}, buffer *bytes.Buffer, typeSerializer *graphBinaryTypeSerializer) ([]byte, error) {
 	p := value.(*Path)
 	_, err := typeSerializer.write(p.Labels, buffer)
@@ -1049,11 +1050,11 @@
 
 // {fully qualified id}{unqualified label}
 func vertexReader(data *[]byte, i *int) (interface{}, error) {
-	return vertexReaderNullByte(data, i, true)
+	return vertexReaderReadingProperties(data, i, true)
 }
 
-// {fully qualified id}{unqualified label}{[unused null byte]}
-func vertexReaderNullByte(data *[]byte, i *int, unusedByte bool) (interface{}, error) {
+// {fully qualified id}{unqualified label}{fully qualified properties}
+func vertexReaderReadingProperties(data *[]byte, i *int, readProperties bool) (interface{}, error) {
 	var err error
 	v := new(Vertex)
 	v.Id, err = readFullyQualifiedNullable(data, i, true)
@@ -1065,33 +1066,43 @@
 		return nil, err
 	}
 	v.Label = label.(string)
-	if unusedByte {
-		*i += 2
+	if readProperties {
+		v.Properties, err = readFullyQualifiedNullable(data, i, true)
+		if err != nil {
+			return nil, err
+		}
 	}
 	return v, nil
 }
 
-// {fully qualified id}{unqualified label}{in vertex w/o null byte}{out vertex}{unused null byte}{unused null byte}
+// {fully qualified id}{unqualified label}{in vertex w/o null byte}{out vertex}{unused null byte}{fully qualified properties}
 func edgeReader(data *[]byte, i *int) (interface{}, error) {
 	var err error
 	e := new(Edge)
 	e.Id, err = readFullyQualifiedNullable(data, i, true)
+	if err != nil {
+		return nil, err
+	}
 	label, err := readUnqualified(data, i, stringType, false)
 	if err != nil {
 		return nil, err
 	}
 	e.Label = label.(string)
-	v, err := vertexReaderNullByte(data, i, false)
+	v, err := vertexReaderReadingProperties(data, i, false)
 	if err != nil {
 		return nil, err
 	}
 	e.InV = *v.(*Vertex)
-	v, err = vertexReaderNullByte(data, i, false)
+	v, err = vertexReaderReadingProperties(data, i, false)
 	if err != nil {
 		return nil, err
 	}
 	e.OutV = *v.(*Vertex)
-	*i += 4
+	*i += 2
+	e.Properties, err = readFullyQualifiedNullable(data, i, true)
+	if err != nil {
+		return nil, err
+	}
 	return e, nil
 }
 
@@ -1129,7 +1140,15 @@
 		return nil, err
 	}
 
-	*i += 4
+	*i += 2
+
+	props, err := readFullyQualifiedNullable(data, i, true)
+	if err != nil {
+		return nil, err
+	}
+
+	vp.Properties = props
+
 	return vp, nil
 }
 
diff --git a/gremlin-go/driver/graphTraversal.go b/gremlin-go/driver/graphTraversal.go
index 796e4dc..ead3057 100644
--- a/gremlin-go/driver/graphTraversal.go
+++ b/gremlin-go/driver/graphTraversal.go
@@ -58,6 +58,12 @@
 	return g
 }
 
+// E adds the e step to the GraphTraversal.
+func (g *GraphTraversal) E(args ...interface{}) *GraphTraversal {
+	g.Bytecode.AddStep("E", args...)
+	return g
+}
+
 // AddE adds the addE step to the GraphTraversal.
 func (g *GraphTraversal) AddE(args ...interface{}) *GraphTraversal {
 	g.Bytecode.AddStep("addE", args...)
diff --git a/gremlin-go/driver/graphTraversalSource_test.go b/gremlin-go/driver/graphTraversalSource_test.go
index ce1ad9a..f33c432 100644
--- a/gremlin-go/driver/graphTraversalSource_test.go
+++ b/gremlin-go/driver/graphTraversalSource_test.go
@@ -27,7 +27,7 @@
 func TestGraphTraversalSource(t *testing.T) {
 
 	t.Run("GraphTraversalSource.With tests", func(t *testing.T) {
-		t.Run("Test for single param", func(t *testing.T) {
+		t.Run("Test for single property", func(t *testing.T) {
 			g := &GraphTraversalSource{graph: &Graph{}, bytecode: NewBytecode(nil), remoteConnection: nil}
 			traversal := g.With("foo", "bar")
 			assert.NotNil(t, traversal)
@@ -40,7 +40,7 @@
 			assert.Equal(t, map[string]interface{}{"foo": "bar"}, config)
 		})
 
-		t.Run("Test for multiple param", func(t *testing.T) {
+		t.Run("Test for multiple property", func(t *testing.T) {
 			g := &GraphTraversalSource{graph: &Graph{}, bytecode: NewBytecode(nil), remoteConnection: nil}
 			traversal := g.With("foo", "bar").With("foo2", "bar2")
 			assert.NotNil(t, traversal)
@@ -53,7 +53,7 @@
 			assert.Equal(t, map[string]interface{}{"foo": "bar", "foo2": "bar2"}, config)
 		})
 
-		t.Run("Test for param replacement", func(t *testing.T) {
+		t.Run("Test for property replacement", func(t *testing.T) {
 			g := &GraphTraversalSource{graph: &Graph{}, bytecode: NewBytecode(nil), remoteConnection: nil}
 			traversal := g.With("foo", "bar").With("foo", "not bar")
 			assert.NotNil(t, traversal)
diff --git a/gremlin-go/driver/graph_test.go b/gremlin-go/driver/graph_test.go
index 1b66b2c..89fb0a2 100644
--- a/gremlin-go/driver/graph_test.go
+++ b/gremlin-go/driver/graph_test.go
@@ -30,7 +30,7 @@
 func TestGraphStructureFunctions(t *testing.T) {
 	t.Run("Test Vertex.String()", func(t *testing.T) {
 		uid, _ := uuid.NewUUID()
-		v := Vertex{Element{uid, "Vertex-Label"}}
+		v := Vertex{Element{uid, "Vertex-Label", nil}}
 		assert.Equal(t, fmt.Sprintf("v[%s]", uid.String()), v.String())
 	})
 
@@ -38,21 +38,21 @@
 		uidEdge, _ := uuid.NewUUID()
 		uidIn, _ := uuid.NewUUID()
 		uidOut, _ := uuid.NewUUID()
-		v := Edge{Element{uidEdge, "edge_label"}, Vertex{Element{uidOut, "vertex_out"}}, Vertex{Element{uidIn, "vertex_in"}}}
+		v := Edge{Element{uidEdge, "edge_label", nil}, Vertex{Element{uidOut, "vertex_out", nil}}, Vertex{Element{uidIn, "vertex_in", nil}}}
 		assert.Equal(t, fmt.Sprintf("e[%s][%s-edge_label->%s]", uidEdge.String(), uidOut.String(), uidIn.String()), v.String())
 	})
 
 	t.Run("Test VertexProperty.String()", func(t *testing.T) {
 		uidVProp, _ := uuid.NewUUID()
 		uidV, _ := uuid.NewUUID()
-		v := VertexProperty{Element{uidVProp, "Vertex-prop"}, "Vertex", []uint32{0, 1}, Vertex{Element{uidV, "Vertex"}}}
+		v := VertexProperty{Element{uidVProp, "Vertex-prop", nil}, "Vertex", []uint32{0, 1}, Vertex{Element{uidV, "Vertex", nil}}}
 		assert.Equal(t, "vp[Vertex-prop->[0 1]]", v.String())
 	})
 
 	t.Run("Test Property.String()", func(t *testing.T) {
 		uidElement, _ := uuid.NewUUID()
 		data := []uint32{0, 1}
-		p := Property{"property-Key", data, Element{uidElement, "prop"}}
+		p := Property{"property-Key", data, Element{uidElement, "prop", nil}}
 		assert.Equal(t, "p[property-Key->[0 1]]", p.String())
 	})
 
diff --git a/gremlin-go/driver/request.go b/gremlin-go/driver/request.go
index d1cd8a9..31a57ef 100644
--- a/gremlin-go/driver/request.go
+++ b/gremlin-go/driver/request.go
@@ -71,6 +71,10 @@
 		newArgs["userAgent"] = requestOptions.userAgent
 	}
 
+	if requestOptions.materializeProperties != "" {
+		newArgs["materializeProperties"] = requestOptions.materializeProperties
+	}
+
 	return request{
 		requestID: requestId,
 		op:        stringOp,
@@ -112,10 +116,11 @@
 // allowedReqArgs contains the arguments that will be extracted from the
 // bytecode and sent with the request.
 var allowedReqArgs = map[string]bool{
-	"evaluationTimeout": true,
-	"batchSize":         true,
-	"requestId":         true,
-	"userAgent":         true,
+	"evaluationTimeout":     true,
+	"batchSize":             true,
+	"requestId":             true,
+	"userAgent":             true,
+	"materializeProperties": true,
 }
 
 // extractReqArgs extracts request arguments from the provided bytecode.
diff --git a/gremlin-go/driver/requestOptions.go b/gremlin-go/driver/requestOptions.go
index 4153eb1..8543864 100644
--- a/gremlin-go/driver/requestOptions.go
+++ b/gremlin-go/driver/requestOptions.go
@@ -24,19 +24,21 @@
 )
 
 type RequestOptions struct {
-	requestID         uuid.UUID
-	evaluationTimeout int
-	batchSize         int
-	userAgent         string
-	bindings          map[string]interface{}
+	requestID             uuid.UUID
+	evaluationTimeout     int
+	batchSize             int
+	userAgent             string
+	bindings              map[string]interface{}
+	materializeProperties string
 }
 
 type RequestOptionsBuilder struct {
-	requestID         uuid.UUID
-	evaluationTimeout int
-	batchSize         int
-	userAgent         string
-	bindings          map[string]interface{}
+	requestID             uuid.UUID
+	evaluationTimeout     int
+	batchSize             int
+	userAgent             string
+	bindings              map[string]interface{}
+	materializeProperties string
 }
 
 func (builder *RequestOptionsBuilder) SetRequestId(requestId uuid.UUID) *RequestOptionsBuilder {
@@ -64,6 +66,11 @@
 	return builder
 }
 
+func (builder *RequestOptionsBuilder) SetMaterializeProperties(materializeProperties string) *RequestOptionsBuilder {
+	builder.materializeProperties = materializeProperties
+	return builder
+}
+
 func (builder *RequestOptionsBuilder) AddBinding(key string, binding interface{}) *RequestOptionsBuilder {
 	if builder.bindings == nil {
 		builder.bindings = make(map[string]interface{})
@@ -80,6 +87,7 @@
 	requestOptions.batchSize = builder.batchSize
 	requestOptions.userAgent = builder.userAgent
 	requestOptions.bindings = builder.bindings
+	requestOptions.materializeProperties = builder.materializeProperties
 
 	return *requestOptions
 }
diff --git a/gremlin-go/driver/requestOptions_test.go b/gremlin-go/driver/requestOptions_test.go
index 6eb6259..972f067 100644
--- a/gremlin-go/driver/requestOptions_test.go
+++ b/gremlin-go/driver/requestOptions_test.go
@@ -44,6 +44,10 @@
 		r := new(RequestOptionsBuilder).SetUserAgent("TestUserAgent").Create()
 		assert.Equal(t, "TestUserAgent", r.userAgent)
 	})
+	t.Run("Test RequestOptionsBuilder with custom materializeProperties", func(t *testing.T) {
+		r := new(RequestOptionsBuilder).SetMaterializeProperties("TestMaterializeProperties").Create()
+		assert.Equal(t, "TestMaterializeProperties", r.materializeProperties)
+	})
 	t.Run("Test RequestOptionsBuilder with custom bindings", func(t *testing.T) {
 		bindings := map[string]interface{}{"x": 2, "y": 5}
 		r := new(RequestOptionsBuilder).SetBindings(bindings).Create()
diff --git a/gremlin-go/driver/result_test.go b/gremlin-go/driver/result_test.go
index 0ef6291..79ec16a 100644
--- a/gremlin-go/driver/result_test.go
+++ b/gremlin-go/driver/result_test.go
@@ -343,7 +343,7 @@
 		element := Element{}
 		r := Result{&element}
 		res := r.String()
-		assert.Equal(t, "result{object=&{<nil> } class=*gremlingo.Element}", res)
+		assert.Equal(t, "result{object=&{<nil>  <nil>} class=*gremlingo.Element}", res)
 	})
 
 	t.Run("Test Result.GetType() simple type", func(t *testing.T) {
diff --git a/gremlin-go/driver/strategies.go b/gremlin-go/driver/strategies.go
index 4e370a8..d67db57 100644
--- a/gremlin-go/driver/strategies.go
+++ b/gremlin-go/driver/strategies.go
@@ -307,9 +307,10 @@
 // IncidentToAdjacentStrategy looks for .OutE().InV(), .InE().OutV() and .BothE().OtherV()
 // and replaces these step sequences with .Out(), .In() or .Both() respectively.
 // The strategy won't modify the traversal if:
-//   the Edge step is labeled
-//   the traversal contains a Path step
-//   the traversal contains a Lambda step
+//
+//	the Edge step is labeled
+//	the traversal contains a Path step
+//	the traversal contains a Lambda step
 func IncidentToAdjacentStrategy() TraversalStrategy {
 	return &traversalStrategy{name: optimizationNamespace + "IncidentToAdjacentStrategy"}
 }
@@ -379,9 +380,10 @@
 // RepeatUnrollStrategy is an OLTP-only strategy that unrolls any RepeatStep if it uses a constant
 // number of loops (Times(x)) and doesn't emit intermittent elements. If any of the following 3 steps appears
 // within the Repeat-traversal, the strategy will not be applied:
-//   DedupGlobalStep
-//   LoopsStep
-//   LambdaHolder
+//
+//	DedupGlobalStep
+//	LoopsStep
+//	LambdaHolder
 func RepeatUnrollStrategy() TraversalStrategy {
 	return &traversalStrategy{name: optimizationNamespace + "RepeatUnrollStrategy"}
 }
diff --git a/gremlin-go/driver/traversal.go b/gremlin-go/driver/traversal.go
index c6a72a6..7b315da 100644
--- a/gremlin-go/driver/traversal.go
+++ b/gremlin-go/driver/traversal.go
@@ -269,6 +269,17 @@
 	Value: "value",
 }
 
+type materializeProperties struct {
+	All    string
+	Tokens string
+}
+
+// MaterializeProperties is string symbols.
+var MaterializeProperties = materializeProperties{
+	All:    "all",
+	Tokens: "tokens",
+}
+
 type merge string
 
 type merges struct {
diff --git a/gremlin-go/go.mod b/gremlin-go/go.mod
index 1a0c21d..39599db 100644
--- a/gremlin-go/go.mod
+++ b/gremlin-go/go.mod
@@ -26,6 +26,7 @@
 	github.com/nicksnyder/go-i18n/v2 v2.2.1
 	github.com/stretchr/testify v1.8.3
 	golang.org/x/text v0.9.0
+	gopkg.in/yaml.v3 v3.0.1
 )
 
 require (
@@ -39,5 +40,4 @@
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/stretchr/objx v0.5.0 // indirect
-	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
diff --git a/gremlin-go/pom.xml b/gremlin-go/pom.xml
index a4bfe84..18a8edb 100644
--- a/gremlin-go/pom.xml
+++ b/gremlin-go/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>tinkerpop</artifactId>
-        <version>3.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-go</artifactId>
     <name>Apache TinkerPop :: Gremlin Go</name>
@@ -170,7 +170,7 @@
                                 <version>${project.version}</version>
                             </dependency>
                             <dependency>
-                                <groupId>org.codehaus.groovy</groupId>
+                                <groupId>org.apache.groovy</groupId>
                                 <artifactId>groovy-all</artifactId>
                                 <version>${groovy.version}</version>
                                 <type>pom</type>
diff --git a/gremlin-groovy/pom.xml b/gremlin-groovy/pom.xml
index a03d905..5f3daa3 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.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-groovy</artifactId>
     <name>Apache TinkerPop :: Gremlin Groovy</name>
@@ -43,49 +43,30 @@
             <version>2.5.1</version>
         </dependency>
         <dependency>
-            <groupId>org.codehaus.groovy</groupId>
+            <groupId>org.apache.groovy</groupId>
             <artifactId>groovy</artifactId>
             <version>${groovy.version}</version>
-            <classifier>indy</classifier>
         </dependency>
         <dependency>
-            <groupId>org.codehaus.groovy</groupId>
+            <groupId>org.apache.groovy</groupId>
             <artifactId>groovy-groovysh</artifactId>
             <version>${groovy.version}</version>
-            <classifier>indy</classifier>
             <exclusions>
-                <!-- exclude non-indy type -->
                 <exclusion>
-                    <groupId>org.codehaus.groovy</groupId>
-                    <artifactId>groovy</artifactId>
+                    <groupId>org.ow2.asm</groupId>
+                    <artifactId>asm-util</artifactId>
                 </exclusion>
             </exclusions>
         </dependency>
         <dependency>
-            <groupId>org.codehaus.groovy</groupId>
+            <groupId>org.apache.groovy</groupId>
             <artifactId>groovy-json</artifactId>
             <version>${groovy.version}</version>
-            <classifier>indy</classifier>
-            <exclusions>
-                <!-- exclude non-indy type -->
-                <exclusion>
-                    <groupId>org.codehaus.groovy</groupId>
-                    <artifactId>groovy</artifactId>
-                </exclusion>
-            </exclusions>
         </dependency>
         <dependency>
-            <groupId>org.codehaus.groovy</groupId>
+            <groupId>org.apache.groovy</groupId>
             <artifactId>groovy-jsr223</artifactId>
             <version>${groovy.version}</version>
-            <classifier>indy</classifier>
-            <exclusions>
-                <!-- exclude non-indy type -->
-                <exclusion>
-                    <groupId>org.codehaus.groovy</groupId>
-                    <artifactId>groovy</artifactId>
-                </exclusion>
-            </exclusions>
         </dependency>
         <dependency>
             <groupId>org.apache.commons</groupId>
@@ -181,7 +162,7 @@
         <profile>
             <id>jdk11</id>
             <activation>
-                <jdk>11</jdk>
+                <jdk>[11,18)</jdk>
             </activation>
             <build>
                 <plugins>
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 117fdd1..f208ecd 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
@@ -124,7 +124,6 @@
     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}}");
         assertEquals(3, engine.eval("int xxx = 1 + 2"));
         assertEquals(4, engine.eval("yyy = xxx + 1"));
         assertEquals(7, engine.eval("def zzz = yyy + xxx"));
@@ -140,7 +139,6 @@
             assertThat(root, instanceOf(MissingPropertyException.class));
         }
 
-        assertEquals(9, engine.eval("new A().sub(10, 1)"));
         assertEquals(10, engine.eval("addItUp(zzz,xxx)"));
     }
 
diff --git a/gremlin-javascript/pom.xml b/gremlin-javascript/pom.xml
index f1fcb98..4d7b9ef 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.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-javascript</artifactId>
     <name>Apache TinkerPop :: Gremlin Javascript</name>
@@ -79,7 +79,7 @@
 						<scope>runtime</scope>
 					</dependency>
                     <dependency>
-                        <groupId>org.codehaus.groovy</groupId>
+                        <groupId>org.apache.groovy</groupId>
                         <artifactId>groovy-all</artifactId>
                         <version>${groovy.version}</version>
                         <type>pom</type>
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/docker-compose.yml b/gremlin-javascript/src/main/javascript/gremlin-javascript/docker-compose.yml
index 000a3fb..1e7e0e7 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/docker-compose.yml
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/docker-compose.yml
@@ -50,6 +50,7 @@
       - .:/js_app
       - ../../../../../gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features:/gremlin-test
       - ../../../../../docker/gremlin-test-server:/js_app/gremlin-test-server
+      - ../../../../../gremlin-tools/gremlin-socket-server/conf:/js_app/gremlin-socket-server/conf/
     environment:
       - DOCKER_ENVIRONMENT=true
       - TEST_TRANSACTIONS=true
@@ -60,3 +61,8 @@
     depends_on:
       gremlin-server-test-js:
         condition: service_healthy
+  gremlin-socket-server:
+    container_name: gremlin-socket-server-js
+    image: tinkerpop/gremlin-socket-server:${GREMLIN_SERVER}
+    ports:
+      - "45943:45943"
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 4f64f7e..58b8c74 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
@@ -84,6 +84,7 @@
    * @property {Number} batchSize - Indicates whether the Power component is present.
    * @property {String} userAgent - The size in which the result of a request is to be 'batched' back to the client
    * @property {Number} evaluationTimeout - The timeout for the evaluation of the request.
+   * @property {String} materializeProperties - Indicates whether element properties should be returned or not.
    */
 
   /**
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/connection.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/connection.js
index 39bca7c..c691dbd 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/connection.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/connection.js
@@ -68,7 +68,6 @@
    * @param {Boolean} [options.pingEnabled] Setup ping interval. Defaults to: true.
    * @param {Number} [options.pingInterval] Ping request interval in ms if ping enabled. Defaults to: 60000.
    * @param {Number} [options.pongTimeout] Timeout of pong response in ms after sending a ping. Defaults to: 30000.
-   * @param {Boolean} [options.connectOnStartup] Deprecated and non-functional. Open websocket on startup.
    * @constructor
    */
   constructor(url, options) {
@@ -104,12 +103,6 @@
     this._pingEnabled = this.options.pingEnabled === false ? false : true;
     this._pingIntervalDelay = this.options.pingInterval || pingIntervalDelay;
     this._pongTimeoutDelay = this.options.pongTimeout || pongTimeoutDelay;
-
-    if (this.options.connectOnStartup) {
-      console.warn(
-        'connectOnStartup is now deprecated and non-functional. To open a connection, please call open() after instantiating connection object.',
-      );
-    }
   }
 
   /**
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/driver-remote-connection.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/driver-remote-connection.js
index 869d621..605ee2b 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/driver-remote-connection.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/driver-remote-connection.js
@@ -74,7 +74,14 @@
     const optionsStrategy = bytecode.sourceInstructions.find(
       (i) => i[0] === 'withStrategies' && i[1] instanceof OptionsStrategy,
     );
-    const allowedKeys = ['evaluationTimeout', 'scriptEvaluationTimeout', 'batchSize', 'requestId', 'userAgent'];
+    const allowedKeys = [
+      'evaluationTimeout',
+      'scriptEvaluationTimeout',
+      'batchSize',
+      'requestId',
+      'userAgent',
+      'materializeProperties',
+    ];
 
     let requestOptions = undefined;
     if (optionsStrategy !== undefined) {
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
index 292439e..60b03cc 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
@@ -365,6 +365,16 @@
   }
 
   /**
+   * Graph traversal E method.
+   * @param {...Object} args
+   * @returns {GraphTraversal}
+   */
+  E(...args) {
+    this.bytecode.addStep('E', args);
+    return this;
+  }
+
+  /**
    * Graph traversal addE method.
    * @param {...Object} args
    * @returns {GraphTraversal}
@@ -1443,6 +1453,7 @@
  * @type {Object}
  */
 const statics = {
+  E: (...args) => callOnEmptyTraversal('E', args),
   V: (...args) => callOnEmptyTraversal('V', args),
   addE: (...args) => callOnEmptyTraversal('addE', args),
   addV: (...args) => callOnEmptyTraversal('addV', args),
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/VertexPropertySerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/VertexPropertySerializer.js
index 4e38180..308e3b8 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/VertexPropertySerializer.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/VertexPropertySerializer.js
@@ -154,7 +154,7 @@
       // {properties} is a fully qualified typed value composed of {type_code}{type_info}{value_flag}{value} which contains properties. Note that as TinkerPop currently send "references" only, this value will always be null.
       let properties, properties_len;
       try {
-        ({ v: properties, len: properties_len } = this.ioc.unspecifiedNullSerializer.deserialize(cursor));
+        ({ v: properties, len: properties_len } = this.ioc.anySerializer.deserialize(cursor));
         len += properties_len;
       } catch (err) {
         err.message = '{properties}: ' + err.message;
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/package-lock.json b/gremlin-javascript/src/main/javascript/gremlin-javascript/package-lock.json
index 29df437..47aa263 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/package-lock.json
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "gremlin",
-  "version": "3.6.5-alpha1",
+  "version": "3.7.0-alpha1",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "gremlin",
-      "version": "3.6.5-alpha1",
+      "version": "3.7.0-alpha1",
       "license": "Apache-2.0",
       "dependencies": {
         "ws": "^8.11.0"
@@ -2196,14 +2196,10 @@
       }
     },
     "node_modules/js-sdsl": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz",
-      "integrity": "sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==",
-      "dev": true,
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/js-sdsl"
-      }
+      "version": "4.1.4",
+      "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz",
+      "integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==",
+      "dev": true
     },
     "node_modules/js-yaml": {
       "version": "3.14.1",
@@ -5523,9 +5519,9 @@
       "dev": true
     },
     "js-sdsl": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz",
-      "integrity": "sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==",
+      "version": "4.1.4",
+      "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz",
+      "integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==",
       "dev": true
     },
     "js-yaml": {
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/package.json b/gremlin-javascript/src/main/javascript/gremlin-javascript/package.json
index 113fc06..fa88eb1 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.6.5-alpha1",
+  "version": "3.7.0-alpha1",
   "description": "JavaScript Gremlin Language Variant",
   "author": "Apache TinkerPop team",
   "keywords": [
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 8ce0086..a44ebd6 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
@@ -131,17 +131,30 @@
   });
 });
 
+var removeProperties = function(p) {
+  if (p === undefined) {   
+  } else if (p instanceof graphModule.Vertex || p instanceof graphModule.Edge) {
+    p.properties = undefined;
+  } else if (p instanceof Array) {
+    p.forEach(removeProperties)
+  } else if (p instanceof Map) {
+    removeProperties(Array.from(p.keys()))
+    removeProperties(Array.from(p.values()))
+  } else if (p instanceof graphModule.Path) {
+    removeProperties(p.objects)
+  }
+
+  return p
+}
+
 When('iterated to list', function () {
-  return this.traversal.toList().then(list => this.result = list).catch(err => this.result = err);
+  return this.traversal.toList().then(list => this.result = removeProperties(list)).catch(err => this.result = err);
 });
 
 When('iterated next', function () {
   return this.traversal.next().then(it => {
-    this.result = it.value;
-    if (this.result instanceof Path) {
-      // Compare using the objects array
-      this.result = this.result.objects;
-    }
+    // for Path compare using the objects array
+    this.result = removeProperties(it.value instanceof Path ? it.value.objects : it.value )
   }).catch(err => this.result = err);
 });
 
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
index 513042b..0f05259 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
@@ -494,6 +494,12 @@
     g_E_sampleX1X_count: [function({g}) { return g.E().sample(1).count() }], 
     g_V_sampleX1X_byXageX_count: [function({g}) { return g.V().sample(1).by("age").count() }], 
     g_V_order_byXnoX_count: [function({g}) { return g.V().order().by("no").count() }], 
+    g_V_EX11X: [function({g, eid11}) { return g.V().E(eid11) }], 
+    g_EX11X_E: [function({g, eid11}) { return g.E(eid11).E() }], 
+    g_V_EXnullX: [function({g}) { return g.V().E(null) }], 
+    g_V_EXlistXnullXX: [function({g, xx1}) { return g.V().E(xx1) }], 
+    g_injectX1X_EX11_nullX: [function({g, eid11}) { return g.inject(1).E(eid11,null) }], 
+    g_injectX1X_coalesceXEX_hasLabelXtestsX_addEXtestsX_from_V_hasXnameX_XjoshXX_toXV_hasXnameX_XvadasXXX: [function({g}) { return g.addV("person").property("name","josh").addV("person").property("name","vadas") }, function({g}) { return g.inject(1).coalesce(__.E().hasLabel("tests"),__.addE("tests").from_(__.V().has("name","josh")).to(__.V().has("name","vadas"))) }, function({g}) { return g.E().hasLabel("tests") }], 
     g_VX1X_properties_element: [function({g, v2}) { return g.V(v2).properties().element().limit(1) }], 
     g_V_properties_element: [function({g}) { return g.V().properties().element() }], 
     g_V_propertiesXageX_element: [function({g}) { return g.V().properties("age").element() }], 
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/world.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/world.js
index 6e0b7a8..0296a7d 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/world.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/world.js
@@ -108,7 +108,15 @@
 
 function getVertices(connection) {
   const g = traversal().withRemote(connection);
-  return g.V().group().by('name').by(__.tail()).next().then(it => it.value);
+  return g.V().group().by('name').by(__.tail()).next().then(it => {
+    // properties excluded from verification
+    if (it.value instanceof Map) {
+      for (const value of it.value.values()) {
+        value.properties = undefined
+      }
+    }
+    return it.value
+  });
 }
 
 function getEdges(connection) {
@@ -120,6 +128,8 @@
     .then(it => {
       const edges = {};
       it.value.forEach((v, k) => {
+        // properties excluded from verification
+        v.properties = undefined
         edges[getEdgeKey(k)] = v;
       });
       return edges;
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/helper.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/helper.js
index 296f7c3..6232570 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/helper.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/helper.js
@@ -27,14 +27,23 @@
 const Client = require('../lib/driver/client');
 const PlainTextSaslAuthenticator = require('../lib/driver/auth/plain-text-sasl-authenticator');
 
+const yaml = require('js-yaml');
+const fs   = require('fs');
+
 let serverUrl;
 let serverAuthUrl;
+let socketServerUrl;
+let sockerServerConfigPath;
 if (process.env.DOCKER_ENVIRONMENT === 'true') {
   serverUrl = 'ws://gremlin-server-test-js:45940/gremlin';
   serverAuthUrl = 'wss://gremlin-server-test-js:45941/gremlin';
+  socketServerUrl = 'ws://gremlin-socket-server-js:';
+  sockerServerConfigPath = '/js_app/gremlin-socket-server/conf/test-ws-gremlin.yaml';
 } else {
   serverUrl = 'ws://localhost:45940/gremlin';
   serverAuthUrl = 'wss://localhost:45941/gremlin';
+  socketServerUrl = 'ws://localhost:';
+  sockerServerConfigPath = '../../../../../gremlin-tools/gremlin-socket-server/conf/test-ws-gremlin.yaml';
 }
 
 /** @returns {DriverRemoteConnection} */
@@ -68,3 +77,39 @@
     mimeType: process.env.CLIENT_MIMETYPE,
   });
 };
+
+function getMimeTypeFromSocketServerSettings(socketServerSettings) {
+  let mimeType;
+  switch(socketServerSettings.SERIALIZER) {
+    case "GraphSONV2":
+      mimeType = 'application/vnd.gremlin-v2.0+json';
+      break;
+    case "GraphSONV3":
+      mimeType = 'application/vnd.gremlin-v3.0+json';
+      break;
+    case "GraphBinaryV1":
+    default:
+      mimeType = 'application/vnd.graphbinary-v1.0';
+      break;
+  }
+  return mimeType;
+}
+
+exports.getGremlinSocketServerClient = function getGremlinSocketServerClient(traversalSource) {
+  const settings = exports.getGremlinSocketServerSettings();
+  const url = socketServerUrl + settings.PORT + '/gremlin';
+  let mimeType = getMimeTypeFromSocketServerSettings(settings)
+  return new Client(url, { traversalSource, mimeType });
+};
+
+exports.getGremlinSocketServerClientNoUserAgent = function getGremlinSocketServerClient(traversalSource) {
+  const settings = exports.getGremlinSocketServerSettings();
+  const url = socketServerUrl + settings.PORT + '/gremlin';
+  let mimeType = getMimeTypeFromSocketServerSettings(settings)
+  return new Client(url, { traversalSource, mimeType, enableUserAgentOnConnect:false });
+};
+
+exports.getGremlinSocketServerSettings = function getGremlinSocketServerSettings() {
+  const settings = yaml.load(fs.readFileSync(sockerServerConfigPath, 'utf8'));
+  return settings;
+};
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/client-behavior-tests.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/client-behavior-tests.js
new file mode 100644
index 0000000..e20090f
--- /dev/null
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/client-behavior-tests.js
@@ -0,0 +1,77 @@
+/*
+ *  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.
+ */
+
+'use strict';
+
+const assert = require('assert');
+const helper = require('../helper');
+const {getUserAgent} = require("../../lib/utils");
+
+let client;
+let settings;
+
+describe('Client', function () {
+    before(function () {
+        client = helper.getGremlinSocketServerClient('gmodern');
+        settings = helper.getGremlinSocketServerSettings();
+        return client.open();
+    });
+    after(function () {
+        return client.close();
+    });
+    describe('#submit()', function () {
+        it('should reconnect after server closes connection', async function () {
+            let connectionClosed = false;
+            await client.submit('1', null, {requestId: settings.CLOSE_CONNECTION_REQUEST_ID})
+                .catch(function(error){
+                    assert.equal(error.toString(), 'Error: Connection has been closed.');
+                    connectionClosed = true;
+                });
+
+            assert.equal(connectionClosed, true);
+
+            let result = await client.submit('1', null, {requestId: settings.SINGLE_VERTEX_REQUEST_ID})
+            assert.ok(result);
+        });
+        it('should include user agent in handshake request', async function () {
+            let result = await client.submit('1', null, {requestId: settings.USER_AGENT_REQUEST_ID});
+
+            assert.strictEqual(result.first(), getUserAgent());
+        });
+        it('should not include user agent in handshake request if disabled', async function () {
+            let noUserAgentClient = helper.getGremlinSocketServerClientNoUserAgent('gmodern');
+            let result = await noUserAgentClient.submit('1', null,
+                {requestId: settings.USER_AGENT_REQUEST_ID});
+
+            assert.strictEqual(result.first(), "");
+
+            await noUserAgentClient.close();
+        });
+        it('should send per request settings to server', async function () {
+            const resultSet = await client.submit('1', null, {
+                requestId: settings.PER_REQUEST_SETTINGS_REQUEST_ID,
+                evaluationTimeout: 1234,
+                batchSize: 12,
+                userAgent: 'helloWorld'
+            })
+            const expectedResult = `requestId=${settings.PER_REQUEST_SETTINGS_REQUEST_ID} evaluationTimeout=1234, batchSize=12, userAgent=helloWorld`;
+            assert.equal(expectedResult, resultSet.first());
+        });
+    });
+});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/client-tests.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/client-tests.js
index 5765221..ac51dba 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/client-tests.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/client-tests.js
@@ -75,6 +75,98 @@
         });
     });
 
+    it('should handle Vertex properties for bytecode request', function () {
+      return client.submit(new Bytecode().addStep('V', [1]))
+        .then(function (result) {
+          assert.ok(result);
+          assert.strictEqual(result.length, 1);
+          const vertex = result.first().object;
+          assert.ok(vertex instanceof graphModule.Vertex);
+          let age, name
+          if (vertex.properties instanceof Array) {
+            age = vertex.properties[1]
+            name = vertex.properties[0]
+          } else {
+            age = vertex.properties.age[0]
+            name = vertex.properties.name[0]
+          }
+          assert.strictEqual(age.value, 29);
+          assert.strictEqual(name.value, 'marko');
+        });
+    });
+
+    it('should skip Vertex properties for bytecode request with tokens', function () {
+      return client.submit(new Bytecode().addStep('V', [1]), null, {'materializeProperties': 'tokens'})
+        .then(function (result) {
+          assert.ok(result);
+          assert.strictEqual(result.length, 1);
+          const vertex = result.first().object;
+          assert.ok(vertex instanceof graphModule.Vertex);
+          assert.ok(vertex.properties === undefined || vertex.properties.length === 0);
+        });
+    });
+
+    it('should handle Vertex properties for gremlin request', function () {
+      return client.submit('g.V(1)')
+        .then(function (result) {
+          assert.ok(result);
+          assert.strictEqual(result.length, 1);
+          const vertex = result.first();
+          assert.ok(vertex instanceof graphModule.Vertex);
+          let age, name
+          if (vertex.properties instanceof Array) {
+            age = vertex.properties[1]
+            name = vertex.properties[0]
+          } else {
+            age = vertex.properties.age[0]
+            name = vertex.properties.name[0]
+          }
+          assert.strictEqual(age.value, 29);
+          assert.strictEqual(name.value, 'marko');
+        });
+    });
+
+    it('should skip Vertex properties for gremlin request with tokens', function () {
+      return client.submit('g.with("materializeProperties", "tokens").V(1)')
+        .then(function (result) {
+          assert.ok(result);
+          assert.strictEqual(result.length, 1);
+          const vertex = result.first();
+          assert.ok(vertex instanceof graphModule.Vertex);
+          assert.ok(vertex.properties === undefined || vertex.properties.length === 0);
+        });
+    });
+
+    it('should handle VertexProperties properties for gremlin request', async function () {
+      const crewClient = helper.getClient('gcrew');
+      await crewClient.open();
+
+      const result = await crewClient.submit('g.V(7)');
+
+      assert.ok(result);
+      assert.strictEqual(result.length, 1);
+      const vertex = result.first();
+      
+      assertVertexProperties(vertex);
+
+      await crewClient.close();
+    });
+
+    it('should handle VertexProperties properties for bytecode request', async function () {
+      const crewClient = helper.getClient('gcrew');
+      await crewClient.open();
+
+      const result = await crewClient.submit(new Bytecode().addStep('V', [7]));
+
+      assert.ok(result);
+      assert.strictEqual(result.length, 1);
+      const vertex = result.first().object;
+      
+      assertVertexProperties(vertex);
+
+      await crewClient.close();
+    });
+
     it('should be able to stream results from the gremlin server', (done) => {
       const output = [];
       let calls = 0;
@@ -152,3 +244,26 @@
     });
   });
 });
+
+function assertVertexProperties(vertex) {
+  assert.ok(vertex instanceof graphModule.Vertex);
+  let locations;
+  if (vertex.properties instanceof Array) {
+    locations = vertex.properties.filter(p => p.key == 'location');
+  } else {
+    locations = vertex.properties.location
+  }
+  assert.strictEqual(locations.length, 3);
+
+  const vertexProperty = locations[0];
+  assert.strictEqual(vertexProperty.value, 'centreville');
+  if (vertexProperty.properties instanceof Array) {
+    assert.strictEqual(vertexProperty.properties[0].key, 'startTime');
+    assert.strictEqual(vertexProperty.properties[0].value, 1990);
+    assert.strictEqual(vertexProperty.properties[1].key, 'endTime');
+    assert.strictEqual(vertexProperty.properties[1].value, 2000);
+  } else {
+    assert.strictEqual(vertexProperty.properties.startTime, 1990);
+    assert.strictEqual(vertexProperty.properties.endTime, 2000);
+  }
+}
\ No newline at end of file
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 a0b0de1..fee184f 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
@@ -61,6 +61,7 @@
       submit: function (processor, op, args, requestId) {
         assert.strictEqual(args.gremlin, query);
         assert.strictEqual(args.evaluationTimeout, 123);
+        assert.strictEqual(args.materializeProperties, 'tokens');
         assert.strictEqual(processor, customOpProcessor);
 
         return Promise.resolve();
@@ -69,6 +70,6 @@
 
     const customClient = new Client('ws://localhost:9321', {traversalSource: 'g', processor: customOpProcessor, connectOnStartup: false});
     customClient._connection = connectionMock;
-    customClient.submit(query, null, {"evaluationTimeout": 123})
+    customClient.submit(query, null, {'evaluationTimeout': 123, 'materializeProperties': 'tokens'})
   });
 });
diff --git a/gremlin-language/pom.xml b/gremlin-language/pom.xml
index b5c3a53..61224f8 100644
--- a/gremlin-language/pom.xml
+++ b/gremlin-language/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>tinkerpop</artifactId>
-        <version>3.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>gremlin-language</artifactId>
diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 b/gremlin-language/src/main/antlr4/Gremlin.g4
index 2e0ce50..bc41b62 100644
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@ -176,6 +176,7 @@
 
 traversalMethod
 	: traversalMethod_V
+	| traversalMethod_E
 	| traversalMethod_addE
 	| traversalMethod_addV
 	| traversalMethod_mergeE
@@ -286,6 +287,10 @@
 	: 'V' LPAREN genericLiteralList RPAREN
 	;
 
+traversalMethod_E
+	: 'E' LPAREN genericLiteralList RPAREN
+	;
+
 traversalMethod_addE
 	: 'addE' LPAREN stringBasedLiteral RPAREN #traversalMethod_addE_String
 	| 'addE' LPAREN nestedTraversal RPAREN #traversalMethod_addE_Traversal
diff --git a/gremlin-python/docker-compose.yml b/gremlin-python/docker-compose.yml
index 6262c61..2c48b7b 100644
--- a/gremlin-python/docker-compose.yml
+++ b/gremlin-python/docker-compose.yml
@@ -43,6 +43,8 @@
       timeout: 10s
       retries: 30
       start_period: 30s
+    depends_on:
+      - gremlin-socket-server
 
   gremlin-python-integration-tests:
     container_name: gremlin-python-integration-tests
@@ -51,6 +53,8 @@
       - ${BUILD_DIR:-./src/main/python}:/python_app
       - ../gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features:/python_app/gremlin-test/features
       - ../docker/gremlin-test-server:/python_app/gremlin-test-server
+      - ../gremlin-tools/gremlin-socket-server/conf:/python_app/gremlin-socket-server/conf/
+
     environment:
       - TEST_TRANSACTIONS=${TEST_TRANSACTIONS:-true}
       - DEBIAN_FRONTEND=noninteractive
@@ -60,6 +64,8 @@
       - GREMLIN_SERVER_BASIC_AUTH_URL=wss://gremlin-server-test-python:{}/gremlin
       - KRB_HOSTNAME=${KRB_HOSTNAME:-gremlin-server-test}
       - VERSION=${VERSION}
+      - GREMLIN_SOCKET_SERVER_URL=ws://gremlin-socket-server-python:{}/gremlin
+      - GREMLIN_SOCKET_SERVER_CONFIG_PATH=/python_app/gremlin-socket-server/conf/test-ws-gremlin.yaml
     working_dir: /python_app
     command: >
       bash -c "apt-get update && apt-get -y install libkrb5-dev krb5-user
@@ -87,3 +93,9 @@
     command: >
       bash -c "python3 setup.py sdist bdist_wheel;
       EXIT_CODE=$$?; chown -R `stat -c "%u:%g" .` .; exit $$EXIT_CODE"
+
+  gremlin-socket-server:
+    container_name: gremlin-socket-server-python
+    image: tinkerpop/gremlin-socket-server:${GREMLIN_SERVER}
+    ports:
+      - "45943:45943"
diff --git a/gremlin-python/pom.xml b/gremlin-python/pom.xml
index 441d054..c859769 100644
--- a/gremlin-python/pom.xml
+++ b/gremlin-python/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>tinkerpop</artifactId>
-        <version>3.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-python</artifactId>
     <name>Apache TinkerPop :: Gremlin Python</name>
@@ -193,7 +193,7 @@
                                 <version>${project.version}</version>
                             </dependency>
                             <dependency>
-                                <groupId>org.codehaus.groovy</groupId>
+                                <groupId>org.apache.groovy</groupId>
                                 <artifactId>groovy-all</artifactId>
                                 <version>${groovy.version}</version>
                                 <type>pom</type>
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
index 8d75f1d..6058a6b 100644
--- 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
@@ -175,7 +175,7 @@
                                  if x[0] == "withStrategies" and type(x[1]) is OptionsStrategy), None)
         request_options = None
         if options_strategy:
-            allowed_keys = ['evaluationTimeout', 'scriptEvaluationTimeout', 'batchSize', 'requestId', 'userAgent']
+            allowed_keys = ['evaluationTimeout', 'scriptEvaluationTimeout', 'batchSize', 'requestId', 'userAgent', 'materializeProperties']
             request_options = {allowed: options_strategy[1].configuration[allowed] for allowed in allowed_keys
                                if allowed in options_strategy[1].configuration}
         return request_options
diff --git a/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py b/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py
index db1b22a..3decfb2 100644
--- a/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py
+++ b/gremlin-python/src/main/python/gremlin_python/process/graph_traversal.py
@@ -274,6 +274,10 @@
         self.bytecode.add_step("V", *args)
         return self
 
+    def E(self, *args):
+        self.bytecode.add_step("E", *args)
+        return self
+
     def addE(self, *args):
         warnings.warn(
             "gremlin_python.process.GraphTraversal.addE will be replaced by "
@@ -927,6 +931,10 @@
         return __.inject(*args)
 
     @classmethod
+    def E(cls, *args):
+        return cls.graph_traversal(None, None, Bytecode()).E(*args)
+
+    @classmethod
     def V(cls, *args):
         return cls.graph_traversal(None, None, Bytecode()).V(*args)
 
@@ -1582,6 +1590,10 @@
         return session
 
 
+def E(*args):
+    return __.E(*args)
+
+
 def V(*args):
     return __.V(*args)
 
diff --git a/gremlin-python/src/main/python/gremlin_python/structure/graph.py b/gremlin-python/src/main/python/gremlin_python/structure/graph.py
index 751f0bb..75082dc 100644
--- a/gremlin-python/src/main/python/gremlin_python/structure/graph.py
+++ b/gremlin-python/src/main/python/gremlin_python/structure/graph.py
@@ -43,9 +43,10 @@
 
 
 class Element(object):
-    def __init__(self, id, label):
+    def __init__(self, id, label, properties=None):
         self.id = id
         self.label = label
+        self.properties = properties
 
     def __eq__(self, other):
         return isinstance(other, self.__class__) and self.id == other.id
@@ -55,16 +56,16 @@
 
 
 class Vertex(Element):
-    def __init__(self, id, label="vertex"):
-        Element.__init__(self, id, label)
+    def __init__(self, id, label="vertex", properties=None):
+        Element.__init__(self, id, label, properties)
 
     def __repr__(self):
         return "v[" + str(self.id) + "]"
 
 
 class Edge(Element):
-    def __init__(self, id, outV, label, inV):
-        Element.__init__(self, id, label)
+    def __init__(self, id, outV, label, inV, properties=None):
+        Element.__init__(self, id, label, properties)
         self.outV = outV
         self.inV = inV
 
@@ -73,8 +74,8 @@
 
 
 class VertexProperty(Element):
-    def __init__(self, id, label, value, vertex):
-        Element.__init__(self, id, label)
+    def __init__(self, id, label, value, vertex, properties=None):
+        Element.__init__(self, id, label, properties)
         self.value = value
         self.key = self.label
         self.vertex = vertex
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
index 47a777e..d6f5373 100644
--- a/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV1.py
+++ b/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV1.py
@@ -601,8 +601,9 @@
         edgelbl = r.to_object(b, DataType.string, False)
         inv = Vertex(r.read_object(b), r.to_object(b, DataType.string, False))
         outv = Vertex(r.read_object(b), r.to_object(b, DataType.string, False))
-        edge = Edge(edgeid, outv, edgelbl, inv)
-        b.read(4)
+        b.read(2)
+        properties = r.read_object(b)
+        edge = Edge(edgeid, outv, edgelbl, inv, properties)
         return edge
 
 
@@ -680,8 +681,7 @@
 
     @classmethod
     def _read_vertex(cls, b, r):
-        vertex = Vertex(r.read_object(b), r.to_object(b, DataType.string, False))
-        b.read(2)
+        vertex = Vertex(r.read_object(b), r.to_object(b, DataType.string, False), r.read_object(b))
         return vertex
 
 
@@ -707,7 +707,8 @@
     @classmethod
     def _read_vertexproperty(cls, b, r):
         vp = VertexProperty(r.read_object(b), r.to_object(b, DataType.string, False), r.read_object(b), None)
-        b.read(4)
+        b.read(2)
+        vp.properties = r.read_object(b)
         return vp
 
 
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
index 1b05989..2442a7c 100644
--- a/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV2d0.py
+++ b/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV2d0.py
@@ -561,7 +561,12 @@
 
     @classmethod
     def objectify(cls, d, reader):
-        return Vertex(reader.to_object(d["id"]), d.get("label", "vertex"))
+        properties = None
+        if "properties" in d:
+            properties = reader.to_object(d["properties"])
+            if properties is not None:
+                properties = [item for sublist in properties.values() for item in sublist]
+        return Vertex(reader.to_object(d["id"]), d.get("label", "vertex"), properties)
 
 
 class EdgeDeserializer(_GraphSONTypeIO):
@@ -569,10 +574,16 @@
 
     @classmethod
     def objectify(cls, d, reader):
+        properties = None
+        if "properties" in d:
+            properties = reader.to_object(d["properties"])
+            if properties is not None:
+                properties = list(properties.values())
         return Edge(reader.to_object(d["id"]),
                     Vertex(reader.to_object(d["outV"]), d.get("outVLabel", "vertex")),
                     d.get("label", "edge"),
-                    Vertex(reader.to_object(d["inV"]), d.get("inVLabel", "vertex")))
+                    Vertex(reader.to_object(d["inV"]), d.get("inVLabel", "vertex")),
+                    properties)
 
 
 class VertexPropertyDeserializer(_GraphSONTypeIO):
@@ -580,11 +591,17 @@
 
     @classmethod
     def objectify(cls, d, reader):
+        properties = None
+        if "properties" in d:
+            properties = reader.to_object(d["properties"])
+            if properties is not None:
+                properties = list(map(lambda x: Property(x[0], x[1], None), properties.items()))
         vertex = Vertex(reader.to_object(d.get("vertex"))) if "vertex" in d else None
         return VertexProperty(reader.to_object(d["id"]),
                               d["label"],
                               reader.to_object(d["value"]),
-                              vertex)
+                              vertex,
+                              properties)
 
 
 class PropertyDeserializer(_GraphSONTypeIO):
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
index b7a165a..6dd6b15 100644
--- a/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV3d0.py
+++ b/gremlin-python/src/main/python/gremlin_python/structure/io/graphsonV3d0.py
@@ -659,7 +659,12 @@
 
     @classmethod
     def objectify(cls, d, reader):
-        return Vertex(reader.to_object(d["id"]), d.get("label", "vertex"))
+        properties = None
+        if "properties" in d:
+            properties = reader.to_object(d["properties"])
+            if properties is not None:
+                properties = [item for sublist in properties.values() for item in sublist]
+        return Vertex(reader.to_object(d["id"]), d.get("label", "vertex"), properties)
 
 
 class EdgeDeserializer(_GraphSONTypeIO):
@@ -667,10 +672,16 @@
 
     @classmethod
     def objectify(cls, d, reader):
+        properties = None
+        if "properties" in d:
+            properties = reader.to_object(d["properties"])
+            if properties is not None:
+                properties = list(properties.values())
         return Edge(reader.to_object(d["id"]),
                     Vertex(reader.to_object(d["outV"]), d.get("outVLabel", "vertex")),
                     d.get("label", "edge"),
-                    Vertex(reader.to_object(d["inV"]), d.get("inVLabel", "vertex")))
+                    Vertex(reader.to_object(d["inV"]), d.get("inVLabel", "vertex")),
+                    properties)
 
 
 class VertexPropertyDeserializer(_GraphSONTypeIO):
@@ -678,11 +689,17 @@
 
     @classmethod
     def objectify(cls, d, reader):
+        properties = None
+        if "properties" in d:
+            properties = reader.to_object(d["properties"])
+            if properties is not None:
+                properties = list(map(lambda x: Property(x[0], x[1], None), properties.items()))
         vertex = Vertex(reader.to_object(d.get("vertex"))) if "vertex" in d else None
         return VertexProperty(reader.to_object(d["id"]),
                               d["label"],
                               reader.to_object(d["value"]),
-                              vertex)
+                              vertex,
+                              properties)
 
 
 class PropertyDeserializer(_GraphSONTypeIO):
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index 998289b..9fab78c 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -476,6 +476,12 @@
     'g_E_sampleX1X_count': [(lambda g:g.E().sample(1).count())], 
     'g_V_sampleX1X_byXageX_count': [(lambda g:g.V().sample(1).by('age').count())], 
     'g_V_order_byXnoX_count': [(lambda g:g.V().order().by('no').count())], 
+    'g_V_EX11X': [(lambda g, eid11=None:g.V().E(eid11))], 
+    'g_EX11X_E': [(lambda g, eid11=None:g.E(eid11).E())], 
+    'g_V_EXnullX': [(lambda g:g.V().E(None))], 
+    'g_V_EXlistXnullXX': [(lambda g, xx1=None:g.V().E(xx1))], 
+    'g_injectX1X_EX11_nullX': [(lambda g, eid11=None:g.inject(1).E(eid11,None))], 
+    'g_injectX1X_coalesceXEX_hasLabelXtestsX_addEXtestsX_from_V_hasXnameX_XjoshXX_toXV_hasXnameX_XvadasXXX': [(lambda g:g.addV('person').property('name','josh').addV('person').property('name','vadas')), (lambda g:g.inject(1).coalesce(__.E().hasLabel('tests'),__.addE('tests').from_(__.V().has('name','josh')).to(__.V().has('name','vadas')))), (lambda g:g.E().hasLabel('tests'))], 
     'g_VX1X_properties_element': [(lambda g, v2=None:g.V(v2).properties().element()[0:1])], 
     'g_V_properties_element': [(lambda g:g.V().properties().element())], 
     'g_V_propertiesXageX_element': [(lambda g:g.V().properties('age').element())], 
diff --git a/gremlin-python/src/main/python/setup.py b/gremlin-python/src/main/python/setup.py
index 71b17a6..2ca7e9a 100644
--- a/gremlin-python/src/main/python/setup.py
+++ b/gremlin-python/src/main/python/setup.py
@@ -76,7 +76,8 @@
         'pytest>=4.6.4,<7.2.0',
         'mock>=3.0.5,<5.0.0',
         'radish-bdd==0.13.4',
-        'PyHamcrest>=1.9.0,<3.0.0'
+        'PyHamcrest>=1.9.0,<3.0.0',
+        'PyYAML>=5.3'
     ],
     install_requires=install_requires,
     extras_require={
diff --git a/gremlin-python/src/main/python/tests/conftest.py b/gremlin-python/src/main/python/tests/conftest.py
index a3b76a4..5c655fc 100644
--- a/gremlin-python/src/main/python/tests/conftest.py
+++ b/gremlin-python/src/main/python/tests/conftest.py
@@ -25,6 +25,8 @@
 import logging
 import queue
 
+import yaml
+
 from gremlin_python.driver.client import Client
 from gremlin_python.driver.connection import Connection
 from gremlin_python.driver import serializer
@@ -38,16 +40,22 @@
 
 gremlin_server_url = os.environ.get('GREMLIN_SERVER_URL', 'ws://localhost:{}/gremlin')
 gremlin_basic_auth_url = os.environ.get('GREMLIN_SERVER_BASIC_AUTH_URL', 'wss://localhost:{}/gremlin')
+gremlin_socket_server_url = os.environ.get('GREMLIN_SOCKET_SERVER_URL', 'ws://localhost:{}/gremlin')
+gremlin_socket_server_config_path = os.environ.get("GREMLIN_SOCKET_SERVER_CONFIG_PATH",
+                                                   "../../../../../../gremlin-tools/gremlin-socket-server/conf/"
+                                                   "test-ws-gremlin.yaml")
 kerberos_hostname = os.environ.get('KRB_HOSTNAME', socket.gethostname())
 anonymous_url = gremlin_server_url.format(45940)
 basic_url = gremlin_basic_auth_url.format(45941)
 kerberos_url = gremlin_server_url.format(45942)
+
 kerberized_service = 'test-service@{}'.format(kerberos_hostname)
 verbose_logging = False
 
 logging.basicConfig(format='%(asctime)s [%(levelname)8s] [%(filename)15s:%(lineno)d - %(funcName)10s()] - %(message)s',
                     level=logging.DEBUG if verbose_logging else logging.INFO)
 
+
 @pytest.fixture
 def connection(request):
     protocol = GremlinServerWSProtocol(
@@ -84,6 +92,55 @@
         return client
 
 
+@pytest.fixture
+def gremlin_socket_server_serializer(socket_server_settings):
+    if socket_server_settings["SERIALIZER"] == "GraphBinaryV1":
+        return serializer.GraphBinarySerializersV1()
+    elif socket_server_settings["SERIALIZER"] == "GraphSONV2":
+        return serializer.GraphSONSerializersV2d0()
+    elif socket_server_settings["SERIALIZER"] == "GraphSONV3":
+        return serializer.GraphSONSerializersV3d0()
+    else:
+        return serializer.GraphBinarySerializersV1()
+
+
+@pytest.fixture
+def socket_server_client(request, socket_server_settings, gremlin_socket_server_serializer):
+    url = gremlin_socket_server_url.format(socket_server_settings["PORT"])
+    try:
+        client = Client(url, 'g', pool_size=1, message_serializer=gremlin_socket_server_serializer)
+    except OSError:
+        pytest.skip('Gremlin Socket Server is not running')
+    else:
+        def fin():
+            client.close()
+
+        request.addfinalizer(fin)
+        return client
+
+
+@pytest.fixture
+def socket_server_client_no_user_agent(request, socket_server_settings, gremlin_socket_server_serializer):
+    url = gremlin_socket_server_url.format(socket_server_settings["PORT"])
+    try:
+        client = Client(url, 'g', pool_size=1, message_serializer=gremlin_socket_server_serializer,
+                        enable_user_agent_on_connect=False)
+    except OSError:
+        pytest.skip('Gremlin Socket Server is not running')
+    else:
+        def fin():
+            client.close()
+
+        request.addfinalizer(fin)
+        return client
+
+
+@pytest.fixture
+def socket_server_settings():
+    with open(gremlin_socket_server_config_path, mode="rb") as file:
+        settings = yaml.safe_load(file)
+    return settings
+
 @pytest.fixture(params=['basic', 'kerberos'])
 def authenticated_client(request):
     try:
@@ -132,6 +189,30 @@
 
 
 @pytest.fixture(params=['graphsonv2', 'graphsonv3', 'graphbinaryv1'])
+def remote_connection_crew(request):
+    try:
+        if request.param == 'graphbinaryv1':
+            remote_conn = DriverRemoteConnection(anonymous_url, 'gcrew',
+                                                 message_serializer=serializer.GraphBinarySerializersV1())
+        elif request.param == 'graphsonv2':
+            remote_conn = DriverRemoteConnection(anonymous_url, 'gcrew',
+                                                 message_serializer=serializer.GraphSONSerializersV2d0())
+        elif request.param == 'graphsonv3':
+            remote_conn = DriverRemoteConnection(anonymous_url, 'gcrew',
+                                                 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=['graphsonv2', 'graphsonv3', 'graphbinaryv1'])
 def remote_transaction_connection(request):
     try:
         if request.param == 'graphbinaryv1':
diff --git a/gremlin-python/src/main/python/tests/driver/test_client.py b/gremlin-python/src/main/python/tests/driver/test_client.py
index e19da2c..d1dd868 100644
--- a/gremlin-python/src/main/python/tests/driver/test_client.py
+++ b/gremlin-python/src/main/python/tests/driver/test_client.py
@@ -26,7 +26,7 @@
 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
+from gremlin_python.structure.graph import Graph, Vertex
 from gremlin_python.driver.aiohttp.transport import AiohttpTransport
 from gremlin_python.statics import *
 from asyncio import TimeoutError
@@ -147,6 +147,25 @@
     assert asyncio.get_event_loop().run_until_complete(async_connect(True))
 
 
+def test_client_gremlin(client):
+    result_set = client.submit('g.V(1)')
+    result = result_set.all().result()
+    assert 1 == len(result)
+    vertex = result[0]
+    assert type(vertex) is Vertex
+    assert 1 == vertex.id
+    assert 2 == len(vertex.properties)
+    assert 'name' == vertex.properties[0].key
+    assert 'marko' == vertex.properties[0].value
+    ##
+    result_set = client.submit('g.with("materializeProperties", "tokens").V(1)')
+    result = result_set.all().result()
+    assert 1 == len(result)
+    vertex = result[0]
+    assert 1 == vertex.id
+    assert 0 == len(vertex.properties)
+
+
 def test_client_bytecode(client):
     g = Graph().traversal()
     t = g.V()
diff --git a/gremlin-python/src/main/python/tests/driver/test_web_socket_client_behavior.py b/gremlin-python/src/main/python/tests/driver/test_web_socket_client_behavior.py
new file mode 100644
index 0000000..cd23f18
--- /dev/null
+++ b/gremlin-python/src/main/python/tests/driver/test_web_socket_client_behavior.py
@@ -0,0 +1,92 @@
+#
+# 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__ = 'Cole Greer (cole@colegreer.ca)'
+
+
+import re
+import operator
+from functools import reduce
+from gremlin_python.driver import useragent
+
+
+# Note: This test demonstrates different behavior in response to a server sending a close frame than the other GLV's.
+# Other GLV's will respond to this by trying to reconnect. This test is also demonstrating incorrect behavior of
+# client.is_closed() as it appears unaware that the event loop is dead.
+# These differences from other GLV's are being tracked in [TINKERPOP-2846]. If this behavior is changed to resemble
+# other GLV's, this test should be updated to show a vertex is being received by the second request.
+def test_does_not_create_new_connection_if_closed_by_server(socket_server_client, socket_server_settings):
+    try:
+        socket_server_client.submit(
+            "1", request_options={'requestId': socket_server_settings["CLOSE_CONNECTION_REQUEST_ID"]}).all().result()
+    except RuntimeError as err:
+        assert str(err) == "Connection was closed by server."
+
+    assert not socket_server_client.is_closed()
+
+    try:
+        response = socket_server_client.submit(
+            "1", request_options={'requestId': socket_server_settings["SINGLE_VERTEX_REQUEST_ID"]}).all().result()
+    except RuntimeError as err:
+        assert str(err) == "Event loop is closed"
+
+    assert not socket_server_client.is_closed()
+
+
+# Tests that client is correctly sending user agent during web socket handshake by having the server return
+# the captured user agent.
+def test_should_include_user_agent_in_handshake_request(socket_server_client, socket_server_settings):
+    user_agent_response = socket_server_client.submit(
+        "1", request_options={'requestId': socket_server_settings["USER_AGENT_REQUEST_ID"]}).one()[0]
+
+    assert user_agent_response == useragent.userAgent
+
+
+# Tests that no user agent (other than the default one provided by aiohttp) is sent to server when that
+# behaviour is disabled.
+def test_should_not_include_user_agent_in_handshake_request_if_disabled(socket_server_client_no_user_agent,
+                                                                        socket_server_settings):
+    user_agent_response = socket_server_client_no_user_agent.submit(
+        "1", request_options={'requestId': socket_server_settings["USER_AGENT_REQUEST_ID"]}).one()[0]
+
+    # If the gremlin user agent is disabled, the underlying web socket library reverts to sending its default user agent
+    # during connection requests.
+    assert re.search("^Python/(\d\.)*\d aiohttp/(\d\.)*\d$", user_agent_response)
+
+# Tests that client is correctly sending all overridable per request settings (requestId, batchSize,
+# evaluationTimeout, and userAgent) to the server.
+def test_should_send_per_request_settings_to_server(socket_server_client, socket_server_settings):
+
+    result = socket_server_client.submit(
+        "1", request_options={
+            'requestId': socket_server_settings["PER_REQUEST_SETTINGS_REQUEST_ID"],
+            'evaluationTimeout': 1234,
+            'batchSize': 12,
+            'userAgent': "helloWorld"
+        }).all().result()
+
+    expected_result = "requestId={} evaluationTimeout={}, batchSize={}, userAgent={}".format(
+        socket_server_settings["PER_REQUEST_SETTINGS_REQUEST_ID"], 1234, 12, "helloWorld"
+    )
+
+    # Socket Server is sending a simple string response which after being serialized in and out of graphBinary,
+    # becomes a list of length 1 strings. This operation folds the list back to a single string for comparison.
+    result = reduce(operator.add, result)
+
+    assert result == expected_result
diff --git a/gremlin-python/src/main/python/tests/process/test_translator.py b/gremlin-python/src/main/python/tests/process/test_translator.py
index e0230d6..61db50a 100644
--- a/gremlin-python/src/main/python/tests/process/test_translator.py
+++ b/gremlin-python/src/main/python/tests/process/test_translator.py
@@ -350,6 +350,12 @@
         # 98

         tests.append([g.withComputer().V().shortestPath().with_(ShortestPath.target, __.has('name','peter')),

                      "g.withStrategies(new VertexProgramStrategy()).V().shortestPath().with('~tinkerpop.shortestPath.target',__.has('name','peter'))"])

+        # 99

+        tests.append([g.V().coalesce(__.E(),__.addE('person')),

+                     "g.V().coalesce(__.E(),__.addE('person'))"])

+        # 100

+        tests.append([g.inject(1).E(),

+                     "g.inject(1).E()"])

 

         tlr = Translator().of('g')

 

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
index c0c8dc9..5f5f7f0 100644
--- a/gremlin-python/src/main/python/tests/structure/io/test_functionalityio.py
+++ b/gremlin-python/src/main/python/tests/structure/io/test_functionalityio.py
@@ -25,6 +25,61 @@
 from gremlin_python.statics import *
 
 
+def test_vertex(remote_connection):
+    g = Graph().traversal().with_remote(remote_connection)
+    vertex = g.V(1).next()
+    assert vertex.id == 1
+    assert vertex.label == 'person'
+    assert len(vertex.properties) == 2
+    assert vertex.properties[0].key == 'name'
+    assert vertex.properties[0].value == 'marko'
+    assert vertex.properties[1].key == 'age'
+    assert vertex.properties[1].value == 29
+
+
+def test_vertex_without_properties(remote_connection):
+    g = Graph().traversal().with_remote(remote_connection)
+    vertex = g.with_('materializeProperties', 'tokens').V(1).next()
+    assert vertex.id == 1
+    assert vertex.label == 'person'
+    # empty array for GraphBinary and missing field for GraphSON
+    assert vertex.properties is None or len(vertex.properties) == 0
+
+
+def test_edge(remote_connection):
+    g = Graph().traversal().with_remote(remote_connection)
+    edge = g.E(7).next()
+    assert edge.id == 7
+    assert edge.label == 'knows'
+    assert len(edge.properties) == 1
+    assert edge.properties[0].key == 'weight'
+    assert edge.properties[0].value == 0.5
+
+
+def test_edge_without_properties(remote_connection):
+    g = Graph().traversal().with_remote(remote_connection)
+    edge = g.with_('materializeProperties', 'tokens').E(7).next()
+    assert edge.id == 7
+    assert edge.label == 'knows'
+    # empty array for GraphBinary and missing field for GraphSON
+    assert edge.properties is None or len(edge.properties) == 0
+
+
+def test_vertex_vertex_properties(remote_connection_crew):
+    g = Graph().traversal().withRemote(remote_connection_crew)
+    vertex = g.V(7).next()
+    assert vertex.id == 7
+    assert vertex.label == 'person'
+    assert len(vertex.properties) == 4
+    assert vertex.properties[1].key == 'location'
+    assert vertex.properties[1].value == 'centreville'
+    assert len(vertex.properties[1].properties) == 2
+    assert vertex.properties[1].properties[0].key == 'startTime'
+    assert vertex.properties[1].properties[0].value == 1990
+    assert vertex.properties[1].properties[1].key == 'endTime'
+    assert vertex.properties[1].properties[1].value == 2000
+
+
 def test_timestamp(remote_connection):
     g = Graph().traversal().withRemote(remote_connection)
     ts = timestamp(1481750076295 / 1000)
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
index 34aa44e..a36fbe9 100644
--- a/gremlin-python/src/main/python/tests/structure/io/test_graphsonV2d0.py
+++ b/gremlin-python/src/main/python/tests/structure/io/test_graphsonV2d0.py
@@ -153,6 +153,7 @@
         assert 1 == vertex.id
         assert isinstance(vertex.id, int)
         assert vertex == Vertex(1)
+        assert 2 == len(vertex.properties)
         ##
         vertex = self.graphson_reader.read_object("""
         {"@type":"g:Vertex", "@value":{"id":{"@type":"g:Float","@value":45.23}}}""")
diff --git a/gremlin-server/conf/gremlin-server-classic.yaml b/gremlin-server/conf/gremlin-server-classic.yaml
index 726c007..1db444c 100644
--- a/gremlin-server/conf/gremlin-server-classic.yaml
+++ b/gremlin-server/conf/gremlin-server-classic.yaml
@@ -27,9 +27,9 @@
                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.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
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}        # application/json
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1 }                                                                                                           # application/vnd.graphbinary-v1.0
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}                                                                 # application/vnd.graphbinary-v1.0-stringd
 metrics: {
   slf4jReporter: {enabled: true, interval: 180000}}
 strictTransactionManagement: false
diff --git a/gremlin-server/conf/gremlin-server-modern-readonly.yaml b/gremlin-server/conf/gremlin-server-modern-readonly.yaml
index 1f81f9e..4422ff2 100644
--- a/gremlin-server/conf/gremlin-server-modern-readonly.yaml
+++ b/gremlin-server/conf/gremlin-server-modern-readonly.yaml
@@ -27,9 +27,9 @@
                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.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
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}        # application/json
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1 }                                                                                                           # application/vnd.graphbinary-v1.0
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}                                                                 # application/vnd.graphbinary-v1.0-stringd
 metrics: {
   slf4jReporter: {enabled: true, interval: 180000}}
 strictTransactionManagement: false
diff --git a/gremlin-server/conf/gremlin-server-modern.yaml b/gremlin-server/conf/gremlin-server-modern.yaml
index 70fb2ee..89000c8 100644
--- a/gremlin-server/conf/gremlin-server-modern.yaml
+++ b/gremlin-server/conf/gremlin-server-modern.yaml
@@ -28,9 +28,9 @@
                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.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
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}        # application/json
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1 }                                                                                                           # application/vnd.graphbinary-v1.0
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}                                                                 # application/vnd.graphbinary-v1.0-stringd
 metrics: {
   slf4jReporter: {enabled: true, interval: 180000}}
 strictTransactionManagement: false
diff --git a/gremlin-server/conf/gremlin-server-neo4j.yaml b/gremlin-server/conf/gremlin-server-neo4j.yaml
index d512d06..872aad7 100644
--- a/gremlin-server/conf/gremlin-server-neo4j.yaml
+++ b/gremlin-server/conf/gremlin-server-neo4j.yaml
@@ -38,9 +38,9 @@
                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.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
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}        # application/json
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1 }                                                                                                           # application/vnd.graphbinary-v1.0
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}                                                                 # application/vnd.graphbinary-v1.0-stringd
 processors:
   - { className: org.apache.tinkerpop.gremlin.server.op.session.SessionOpProcessor, config: { sessionTimeout: 28800000 }}
   - { className: org.apache.tinkerpop.gremlin.server.op.traversal.TraversalOpProcessor}
diff --git a/gremlin-server/conf/gremlin-server-rest-modern.yaml b/gremlin-server/conf/gremlin-server-rest-modern.yaml
index a34b14e..4da423f 100644
--- a/gremlin-server/conf/gremlin-server-rest-modern.yaml
+++ b/gremlin-server/conf/gremlin-server-rest-modern.yaml
@@ -28,7 +28,7 @@
                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.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}         # application/json
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}         # application/json
 metrics: {
   slf4jReporter: {enabled: true, interval: 180000}}
 strictTransactionManagement: false
diff --git a/gremlin-server/conf/gremlin-server-rest-secure.yaml b/gremlin-server/conf/gremlin-server-rest-secure.yaml
index 67a040f..c75211b 100644
--- a/gremlin-server/conf/gremlin-server-rest-secure.yaml
+++ b/gremlin-server/conf/gremlin-server-rest-secure.yaml
@@ -37,7 +37,7 @@
                org.apache.tinkerpop.gremlin.groovy.jsr223.GroovyCompilerGremlinPlugin: {enableThreadInterrupt: true, timedInterrupt: 10000, compilation: COMPILE_STATIC, extensions: org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.SimpleSandboxExtension},
                org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [scripts/empty-sample-secure.groovy]}}}}
 serializers:
-  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}        # application/json
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}        # application/json
 processors:
   - { className: org.apache.tinkerpop.gremlin.server.op.session.SessionOpProcessor, config: { sessionTimeout: 28800000 }}
   - { className: org.apache.tinkerpop.gremlin.server.op.traversal.TraversalOpProcessor}
diff --git a/gremlin-server/conf/gremlin-server-secure.yaml b/gremlin-server/conf/gremlin-server-secure.yaml
index 10384e6..2d9ba43 100644
--- a/gremlin-server/conf/gremlin-server-secure.yaml
+++ b/gremlin-server/conf/gremlin-server-secure.yaml
@@ -37,9 +37,9 @@
                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.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
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}        # application/json
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1 }                                                                                                           # application/vnd.graphbinary-v1.0
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}                                                                 # application/vnd.graphbinary-v1.0-stringd
 processors:
   - { className: org.apache.tinkerpop.gremlin.server.op.session.SessionOpProcessor, config: { sessionTimeout: 28800000 }}
   - { className: org.apache.tinkerpop.gremlin.server.op.traversal.TraversalOpProcessor}
diff --git a/gremlin-server/conf/gremlin-server-spark.yaml b/gremlin-server/conf/gremlin-server-spark.yaml
index 3c07cb7..e276b08 100644
--- a/gremlin-server/conf/gremlin-server-spark.yaml
+++ b/gremlin-server/conf/gremlin-server-spark.yaml
@@ -51,9 +51,9 @@
                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.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
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}        # application/json
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1 }                                                                                                           # application/vnd.graphbinary-v1.0
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}                                                                 # application/vnd.graphbinary-v1.0-stringd
 processors:
   - { className: org.apache.tinkerpop.gremlin.server.op.session.SessionOpProcessor, config: { sessionTimeout: 28800000 }}
   - { className: org.apache.tinkerpop.gremlin.server.op.traversal.TraversalOpProcessor}
diff --git a/gremlin-server/conf/gremlin-server.yaml b/gremlin-server/conf/gremlin-server.yaml
index 2d9511c..369fc7d 100644
--- a/gremlin-server/conf/gremlin-server.yaml
+++ b/gremlin-server/conf/gremlin-server.yaml
@@ -28,9 +28,9 @@
                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.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
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}        # application/json
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1 }                                                                                                           # application/vnd.graphbinary-v1.0
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}                                                                 # application/vnd.graphbinary-v1.0-stringd
 processors:
   - { className: org.apache.tinkerpop.gremlin.server.op.session.SessionOpProcessor, config: { sessionTimeout: 28800000 }}
   - { className: org.apache.tinkerpop.gremlin.server.op.traversal.TraversalOpProcessor}
diff --git a/gremlin-server/pom.xml b/gremlin-server/pom.xml
index 35e17cf..e5c4aba 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.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-server</artifactId>
     <name>Apache TinkerPop :: Gremlin Server</name>
@@ -42,7 +42,7 @@
         </dependency>
         <dependency>
             <groupId>org.apache.tinkerpop</groupId>
-            <artifactId>gremlin-driver</artifactId>
+            <artifactId>gremlin-util</artifactId>
             <version>${project.version}</version>
         </dependency>
         <dependency>
@@ -82,6 +82,12 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.tinkerpop</groupId>
+            <artifactId>gremlin-driver</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>com.carrotsearch</groupId>
             <artifactId>junit-benchmarks</artifactId>
             <version>0.7.2</version>
diff --git a/gremlin-server/scripts/empty-sample.groovy b/gremlin-server/scripts/empty-sample.groovy
index f3c6ac4..68f3ab4 100644
--- a/gremlin-server/scripts/empty-sample.groovy
+++ b/gremlin-server/scripts/empty-sample.groovy
@@ -37,9 +37,4 @@
 ] as LifeCycleHook]
 
 // define the default TraversalSource to bind queries to - this one will be named "g".
-// ReferenceElementStrategy converts all graph elements (vertices/edges/vertex properties)
-// to "references" (i.e. just id and label without properties). this strategy was added
-// in 3.4.0 to make all Gremlin Server results consistent across all protocols and
-// serialization formats aligning it with TinkerPop recommended practices for writing
-// Gremlin.
-globals << [g : traversal().withEmbedded(graph).withStrategies(ReferenceElementStrategy)]
\ No newline at end of file
+globals << [g : traversal().withEmbedded(graph)]
\ No newline at end of file
diff --git a/gremlin-server/scripts/generate-classic.groovy b/gremlin-server/scripts/generate-classic.groovy
index 9245b0a..9dae7b5 100644
--- a/gremlin-server/scripts/generate-classic.groovy
+++ b/gremlin-server/scripts/generate-classic.groovy
@@ -30,9 +30,4 @@
 ] as LifeCycleHook]
 
 // define the default TraversalSource to bind queries to - this one will be named "g".
-// ReferenceElementStrategy converts all graph elements (vertices/edges/vertex properties)
-// to "references" (i.e. just id and label without properties). this strategy was added
-// in 3.4.0 to make all Gremlin Server results consistent across all protocols and
-// serialization formats aligning it with TinkerPop recommended practices for writing
-// Gremlin.
-globals << [g : traversal().withEmbedded(graph).withStrategies(ReferenceElementStrategy)]
\ No newline at end of file
+globals << [g : traversal().withEmbedded(graph)]
\ No newline at end of file
diff --git a/gremlin-server/scripts/generate-modern-readonly.groovy b/gremlin-server/scripts/generate-modern-readonly.groovy
index c02e342..e646f77 100644
--- a/gremlin-server/scripts/generate-modern-readonly.groovy
+++ b/gremlin-server/scripts/generate-modern-readonly.groovy
@@ -30,9 +30,4 @@
 ] as LifeCycleHook]
 
 // define the default TraversalSource to bind queries to - this one will be named "g".
-// ReferenceElementStrategy converts all graph elements (vertices/edges/vertex properties)
-// to "references" (i.e. just id and label without properties). this strategy was added
-// in 3.4.0 to make all Gremlin Server results consistent across all protocols and
-// serialization formats aligning it with TinkerPop recommended practices for writing
-// Gremlin.
-globals << [g : traversal().withEmbedded(graph).withStrategies(ReadOnlyStrategy, ReferenceElementStrategy)]
+globals << [g : traversal().withEmbedded(graph).withStrategies(ReadOnlyStrategy)]
diff --git a/gremlin-server/scripts/generate-modern.groovy b/gremlin-server/scripts/generate-modern.groovy
index cd62e98..594402a 100644
--- a/gremlin-server/scripts/generate-modern.groovy
+++ b/gremlin-server/scripts/generate-modern.groovy
@@ -30,9 +30,4 @@
 ] as LifeCycleHook]
 
 // define the default TraversalSource to bind queries to - this one will be named "g".
-// ReferenceElementStrategy converts all graph elements (vertices/edges/vertex properties)
-// to "references" (i.e. just id and label without properties). this strategy was added
-// in 3.4.0 to make all Gremlin Server results consistent across all protocols and
-// serialization formats aligning it with TinkerPop recommended practices for writing
-// Gremlin.
-globals << [g : traversal().withEmbedded(graph).withStrategies(ReferenceElementStrategy)]
\ No newline at end of file
+globals << [g : traversal().withEmbedded(graph)]
\ No newline at end of file
diff --git a/gremlin-server/scripts/load-sample.groovy b/gremlin-server/scripts/load-sample.groovy
index ad2f583..91b3800 100644
--- a/gremlin-server/scripts/load-sample.groovy
+++ b/gremlin-server/scripts/load-sample.groovy
@@ -36,9 +36,4 @@
 ] as LifeCycleHook]
 
 // define the default TraversalSource to bind queries to - this one will be named "g".
-// ReferenceElementStrategy converts all graph elements (vertices/edges/vertex properties)
-// to "references" (i.e. just id and label without properties). this strategy was added
-// in 3.4.0 to make all Gremlin Server results consistent across all protocols and
-// serialization formats aligning it with TinkerPop recommended practices for writing
-// Gremlin.
-globals << [g : traversal().withEmbedded(graph).withStrategies(ReferenceElementStrategy)]
\ No newline at end of file
+globals << [g : traversal().withEmbedded(graph)]
\ No newline at end of file
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 ee02bd8..6ffa958 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
@@ -23,11 +23,11 @@
 import io.netty.handler.ssl.SslContextBuilder;
 import io.netty.handler.ssl.SslProvider;
 import io.netty.handler.timeout.IdleStateHandler;
-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.GraphBinaryMessageSerializerV1;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV2d0;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
+import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV2d0;
 import org.apache.tinkerpop.gremlin.groovy.engine.GremlinExecutor;
 import org.apache.tinkerpop.gremlin.server.auth.Authenticator;
 import org.apache.tinkerpop.gremlin.server.authz.Authorizer;
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Context.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Context.java
index da1c666..720c4d9 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Context.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Context.java
@@ -18,10 +18,13 @@
  */
 package org.apache.tinkerpop.gremlin.server;
 
-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;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.AbstractTraverser;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceFactory;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.groovy.engine.GremlinExecutor;
 import io.netty.channel.ChannelHandlerContext;
 import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptChecker;
@@ -32,6 +35,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.ScheduledExecutorService;
@@ -52,6 +56,7 @@
     private final ScheduledExecutorService scheduledExecutorService;
     private final AtomicBoolean finalResponseWritten = new AtomicBoolean();
     private final long requestTimeout;
+    private final String materializeProperties;
     private final RequestContentType requestContentType;
     private final Object gremlinArgument;
     private final AtomicBoolean startedResponse = new AtomicBoolean(false);
@@ -90,6 +95,7 @@
         this.gremlinArgument = requestMessage.getArgs().get(Tokens.ARGS_GREMLIN);
         this.requestContentType = determineRequestContents();
         this.requestTimeout = determineTimeout();
+        this.materializeProperties = determineMaterializeProperties();
     }
 
     /**
@@ -102,6 +108,10 @@
         return requestTimeout;
     }
 
+    public String getMaterializeProperties() {
+        return materializeProperties;
+    }
+
     public boolean isFinalResponseWritten() {
         return this.finalResponseWritten.get();
     }
@@ -270,4 +280,36 @@
 
         return timeoutDefinedInScript.orElse(seto);
     }
+
+    private String determineMaterializeProperties() {
+        // with() in Script request has the highest priority
+        if (requestContentType == RequestContentType.SCRIPT) {
+            final Optional<String> mp = GremlinScriptChecker.parse(gremlinArgument.toString()).getMaterializeProperties();
+            if (mp.isPresent())
+                return mp.get().equals(Tokens.MATERIALIZE_PROPERTIES_TOKENS)
+                        ? Tokens.MATERIALIZE_PROPERTIES_TOKENS
+                        : Tokens.MATERIALIZE_PROPERTIES_ALL;
+        }
+
+        final Map<String, Object> args = requestMessage.getArgs();
+        // all options except MATERIALIZE_PROPERTIES_TOKENS treated as MATERIALIZE_PROPERTIES_ALL
+        return args.containsKey(Tokens.ARGS_MATERIALIZE_PROPERTIES)
+                && args.get(Tokens.ARGS_MATERIALIZE_PROPERTIES).equals(Tokens.MATERIALIZE_PROPERTIES_TOKENS)
+                ? Tokens.MATERIALIZE_PROPERTIES_TOKENS
+                : Tokens.MATERIALIZE_PROPERTIES_ALL;
+    }
+
+    public void handleDetachment(final List<Object> aggregate) {
+        if (!aggregate.isEmpty() && !this.getMaterializeProperties().equals(Tokens.MATERIALIZE_PROPERTIES_ALL)) {
+            final Object firstElement = aggregate.get(0);
+
+            if (firstElement instanceof Element) {
+                for (int i = 0; i < aggregate.size(); i++)
+                    aggregate.set(i, ReferenceFactory.detach((Element) aggregate.get(i)));
+            } else if (firstElement instanceof AbstractTraverser) {
+                for (final Object item : aggregate)
+                    ((AbstractTraverser) item).detach();
+            }
+        }
+    }
 }
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GraphManager.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GraphManager.java
index d21de8a..bbd9ab5 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GraphManager.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/GraphManager.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.server;
 
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 
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 3286d32..7a21afc 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
@@ -20,7 +20,7 @@
 
 import io.netty.handler.ssl.ClientAuth;
 import io.netty.handler.ssl.SslContext;
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
 import org.apache.tinkerpop.gremlin.jsr223.GremlinPlugin;
 import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngine;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/Authenticator.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/Authenticator.java
index 4f2eb20..d3a291c 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/Authenticator.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/Authenticator.java
@@ -18,9 +18,9 @@
  */
 package org.apache.tinkerpop.gremlin.server.auth;
 
-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.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.server.Channelizer;
 
 import java.net.InetAddress;
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/authz/Authorizer.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/authz/Authorizer.java
index c32b78a..8028bf1 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/authz/Authorizer.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/authz/Authorizer.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.server.authz;
 
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.server.auth.AuthenticatedUser;
@@ -55,7 +55,7 @@
      * {@link AuthorizationException} if this is not the case.
      *
      * @param user {@link AuthenticatedUser} that needs authorization.
-     * @param msg {@link RequestMessage} in which the {@link org.apache.tinkerpop.gremlin.driver.Tokens}.ARGS_GREMLIN argument can contain an arbitrary succession of script statements.
+     * @param msg {@link RequestMessage} in which the {@link org.apache.tinkerpop.gremlin.util.Tokens}.ARGS_GREMLIN argument can contain an arbitrary succession of script statements.
      */
     public void authorize(final AuthenticatedUser user, final RequestMessage msg) throws AuthorizationException;
 
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/AbstractSession.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/AbstractSession.java
index 4b137f3..7c04e9e 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/AbstractSession.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/AbstractSession.java
@@ -23,13 +23,12 @@
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelHandlerContext;
 import org.apache.commons.lang3.exception.ExceptionUtils;
-import org.apache.tinkerpop.gremlin.driver.Client;
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
-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;
-import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.ser.MessageTextSerializer;
 import org.apache.tinkerpop.gremlin.groovy.engine.GremlinExecutor;
 import org.apache.tinkerpop.gremlin.groovy.jsr223.TimedInterruptTimeoutException;
 import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngine;
@@ -737,6 +736,8 @@
         final Map<String, Object> responseMetaData = generateResponseMetaData(sessionTask, code, itty);
         final Map<String, Object> statusAttributes = generateStatusAttributes(sessionTask, code, itty);
         try {
+            sessionTask.handleDetachment(aggregate);
+
             if (useBinary) {
                 return new Frame(serializer.serializeResponseAsBinary(ResponseMessage.build(msg)
                         .code(code)
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/GremlinResponseFrameEncoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/GremlinResponseFrameEncoder.java
index 54fe16b..879b44f 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/GremlinResponseFrameEncoder.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/GremlinResponseFrameEncoder.java
@@ -19,11 +19,10 @@
 package org.apache.tinkerpop.gremlin.server.handler;
 
 import com.codahale.metrics.Meter;
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
-import org.apache.tinkerpop.gremlin.driver.Tokens;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
-import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.ser.MessageTextSerializer;
 import org.apache.tinkerpop.gremlin.server.GremlinServer;
 import org.apache.tinkerpop.gremlin.server.op.session.Session;
 import org.apache.tinkerpop.gremlin.server.util.ExceptionHelper;
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpBasicAuthorizationHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpBasicAuthorizationHandler.java
index 0951a5d..4396085 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpBasicAuthorizationHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpBasicAuthorizationHandler.java
@@ -25,8 +25,8 @@
 import io.netty.handler.codec.http.FullHttpRequest;
 import io.netty.handler.codec.http.HttpUtil;
 import io.netty.util.ReferenceCountUtil;
-import org.apache.tinkerpop.gremlin.driver.Tokens;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.server.GremlinServer;
 import org.apache.tinkerpop.gremlin.server.auth.AuthenticatedUser;
 import org.apache.tinkerpop.gremlin.server.authz.AuthorizationException;
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
index 6995b21..7eda645 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
@@ -19,19 +19,23 @@
 package org.apache.tinkerpop.gremlin.server.handler;
 
 import com.codahale.metrics.Timer;
-import io.netty.buffer.ByteBufAllocator;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
-import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptChecker;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.AbstractTraverser;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceFactory;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
 import org.apache.tinkerpop.gremlin.server.util.TextPlainMessageSerializer;
 import org.javatuples.Pair;
 import org.javatuples.Quartet;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.tinkerpop.gremlin.util.ExceptionHelper;
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
-import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.ser.MessageTextSerializer;
 import org.apache.tinkerpop.gremlin.groovy.engine.GremlinExecutor;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.server.GraphManager;
@@ -222,9 +226,25 @@
 
                             logger.debug("Transforming result of request with script [{}] and bindings of [{}] with result of [{}] on [{}]",
                                     requestArguments.getValue0(), requestArguments.getValue1(), o, Thread.currentThread().getName());
+
+                            final Optional<String> mp = GremlinScriptChecker.parse(requestArguments.getValue0()).getMaterializeProperties();
+                            final List asList = IteratorUtils.asList(o);
+
+                            if (mp.isPresent() && mp.get().equals(Tokens.MATERIALIZE_PROPERTIES_TOKENS)) {
+                                final Object firstElement = asList.get(0);
+
+                                if (firstElement instanceof Element) {
+                                    for (int i = 0; i < asList.size(); i++)
+                                        asList.set(i, ReferenceFactory.detach((Element) asList.get(i)));
+                                } else if (firstElement instanceof AbstractTraverser) {
+                                    for (final Object item : asList)
+                                        ((AbstractTraverser) item).detach();
+                                }
+                            }
+
                             final ResponseMessage responseMessage = ResponseMessage.build(UUID.randomUUID())
                                     .code(ResponseStatusCode.SUCCESS)
-                                    .result(IteratorUtils.asList(o)).create();
+                                    .result(asList).create();
 
                             // http server is sessionless and must handle commit on transactions. the commit occurs
                             // before serialization to be consistent with how things work for websocket based
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpHandlerUtil.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpHandlerUtil.java
index c1ae1e5..1ce6b00 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpHandlerUtil.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpHandlerUtil.java
@@ -31,7 +31,7 @@
 import io.netty.handler.codec.http.QueryStringDecoder;
 import io.netty.util.CharsetUtil;
 import org.apache.commons.lang3.exception.ExceptionUtils;
-import org.apache.tinkerpop.gremlin.driver.Tokens;
+import org.apache.tinkerpop.gremlin.util.Tokens;
 import org.apache.tinkerpop.gremlin.server.GremlinServer;
 import org.apache.tinkerpop.gremlin.server.util.MetricManager;
 import org.apache.tinkerpop.shaded.jackson.databind.JsonNode;
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/MultiTaskSession.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/MultiTaskSession.java
index 1c858a2..fb623a9 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/MultiTaskSession.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/MultiTaskSession.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.server.handler;
 
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.groovy.engine.GremlinExecutor;
 import org.apache.tinkerpop.gremlin.groovy.jsr223.GroovyCompilerGremlinPlugin;
 import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngine;
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpExecutorHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpExecutorHandler.java
index 068c332..8e3b1ee 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpExecutorHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpExecutorHandler.java
@@ -18,9 +18,9 @@
  */
 package org.apache.tinkerpop.gremlin.server.handler;
 
-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.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.groovy.engine.GremlinExecutor;
 import org.apache.tinkerpop.gremlin.server.Context;
 import org.apache.tinkerpop.gremlin.server.GraphManager;
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
index 4259d15..340b913 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
@@ -20,9 +20,9 @@
 
 import io.netty.handler.timeout.IdleState;
 import io.netty.handler.timeout.IdleStateEvent;
-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.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.groovy.engine.GremlinExecutor;
 import org.apache.tinkerpop.gremlin.server.Channelizer;
 import org.apache.tinkerpop.gremlin.server.Context;
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 b53219e..07faaa6 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
@@ -31,10 +31,10 @@
 import java.util.Map;
 
 import io.netty.util.AttributeMap;
-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;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.server.GremlinServer;
 import org.apache.tinkerpop.gremlin.server.Settings;
 import org.apache.tinkerpop.gremlin.server.auth.AuthenticatedUser;
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 32c13da..2c6f037 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
@@ -18,9 +18,9 @@
  */
 package org.apache.tinkerpop.gremlin.server.handler;
 
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
+import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryMapper;
 import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
 
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SessionException.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SessionException.java
index cf577e2..5705de2 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SessionException.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SessionException.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.server.handler;
 
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
 
 /**
  * An exception that holds the error-related {@link ResponseMessage} which is meant to be returned to the calling
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SessionTask.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SessionTask.java
index 57c84f7..5dbe5e0 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SessionTask.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SessionTask.java
@@ -19,7 +19,7 @@
 package org.apache.tinkerpop.gremlin.server.handler;
 
 import io.netty.channel.ChannelHandlerContext;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.groovy.engine.GremlinExecutor;
 import org.apache.tinkerpop.gremlin.server.Context;
 import org.apache.tinkerpop.gremlin.server.GraphManager;
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/StateKey.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/StateKey.java
index 4b5f581..cfb2e32 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/StateKey.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/StateKey.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.server.handler;
 
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.server.auth.AuthenticatedUser;
 import org.apache.tinkerpop.gremlin.server.auth.Authenticator;
 import org.apache.tinkerpop.gremlin.server.op.session.Session;
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/UnifiedHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/UnifiedHandler.java
index c23d7ed..318a0a0 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/UnifiedHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/UnifiedHandler.java
@@ -24,10 +24,10 @@
 import io.netty.handler.timeout.IdleState;
 import io.netty.handler.timeout.IdleStateEvent;
 import io.netty.util.ReferenceCountUtil;
-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;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.groovy.engine.GremlinExecutor;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.Operator;
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WebSocketAuthorizationHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WebSocketAuthorizationHandler.java
index 98a2411..4b8e6f9 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WebSocketAuthorizationHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WebSocketAuthorizationHandler.java
@@ -22,10 +22,10 @@
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
 
-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;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.server.GremlinServer;
 import org.apache.tinkerpop.gremlin.server.auth.AuthenticatedUser;
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 a8a6fa9..227b2f7 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
@@ -18,9 +18,9 @@
  */
 package org.apache.tinkerpop.gremlin.server.handler;
 
-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.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandler;
 import io.netty.channel.ChannelHandlerContext;
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 c9a48c6..5e64eb8 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
@@ -23,9 +23,9 @@
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.MessageToMessageDecoder;
 import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
-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.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
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 4794307..8c564ac 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
@@ -18,10 +18,10 @@
  */
 package org.apache.tinkerpop.gremlin.server.handler;
 
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
-import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
-import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.ser.MessageTextSerializer;
+import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
 import io.netty.channel.ChannelHandler;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.MessageToMessageDecoder;
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsUserAgentHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsUserAgentHandler.java
index cd1e0a6..49d7f15 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsUserAgentHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsUserAgentHandler.java
@@ -24,7 +24,6 @@
 import io.netty.handler.codec.http.HttpHeaders;
 import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
 import io.netty.util.AttributeKey;
-import org.apache.tinkerpop.gremlin.driver.UserAgent;
 import org.apache.tinkerpop.gremlin.server.GremlinServer;
 import org.apache.tinkerpop.gremlin.server.util.MetricManager;
 import org.slf4j.Logger;
@@ -41,16 +40,18 @@
      */
     private static final int MAX_USER_AGENT_METRICS = 10000;
 
+    private static final String USER_AGENT_HEADER_NAME = "User-Agent";
+
     private static final Logger logger = LoggerFactory.getLogger(WsUserAgentHandler.class);
-    public static final AttributeKey<String> USER_AGENT_ATTR_KEY = AttributeKey.valueOf(UserAgent.USER_AGENT_HEADER_NAME);
+    public static final AttributeKey<String> USER_AGENT_ATTR_KEY = AttributeKey.valueOf(USER_AGENT_HEADER_NAME);
 
     @Override
     public void userEventTriggered(final ChannelHandlerContext ctx, java.lang.Object evt) {
         if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
             final HttpHeaders requestHeaders = ((WebSocketServerProtocolHandler.HandshakeComplete) evt).requestHeaders();
 
-            if (requestHeaders.contains(UserAgent.USER_AGENT_HEADER_NAME)){
-                final String userAgent = requestHeaders.get(UserAgent.USER_AGENT_HEADER_NAME);
+            if (requestHeaders.contains(USER_AGENT_HEADER_NAME)){
+                final String userAgent = requestHeaders.get(USER_AGENT_HEADER_NAME);
 
                 ctx.channel().attr(USER_AGENT_ATTR_KEY).set(userAgent);
                 logger.debug("New Connection on channel [{}] with user agent [{}]", ctx.channel().id().asShortText(), userAgent);
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 bc355df..e8735c1 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
@@ -19,10 +19,10 @@
 package org.apache.tinkerpop.gremlin.server.op;
 
 import com.codahale.metrics.Timer;
-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;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.groovy.engine.GremlinExecutor;
 import org.apache.tinkerpop.gremlin.groovy.jsr223.TimedInterruptTimeoutException;
 import org.apache.tinkerpop.gremlin.process.traversal.Failure;
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 a0c3a37..49b9f6f 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
@@ -20,12 +20,12 @@
 
 import io.netty.channel.ChannelHandlerContext;
 import org.apache.commons.lang3.exception.ExceptionUtils;
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
-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;
-import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.ser.MessageTextSerializer;
 import org.apache.tinkerpop.gremlin.process.traversal.Failure;
 import org.apache.tinkerpop.gremlin.server.Context;
 import org.apache.tinkerpop.gremlin.server.GraphManager;
@@ -283,6 +283,8 @@
         try {
             final ChannelHandlerContext nettyContext = ctx.getChannelHandlerContext();
 
+            ctx.handleDetachment(aggregate);
+
             if (useBinary) {
                 return new Frame(serializer.serializeResponseAsBinary(ResponseMessage.build(msg)
                         .code(code)
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/OpProcessorException.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/OpProcessorException.java
index a6ec202..2910112 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/OpProcessorException.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/OpProcessorException.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.server.op;
 
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
 
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)
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 039d1ca..e93377d 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
@@ -19,11 +19,11 @@
 package org.apache.tinkerpop.gremlin.server.op.session;
 
 import io.netty.channel.ChannelHandlerContext;
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
-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;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.groovy.jsr223.GroovyCompilerGremlinPlugin;
 import org.apache.tinkerpop.gremlin.jsr223.JavaTranslator;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/standard/StandardOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/standard/StandardOpProcessor.java
index 81df30c..bb90ec0 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/standard/StandardOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/standard/StandardOpProcessor.java
@@ -18,10 +18,10 @@
  */
 package org.apache.tinkerpop.gremlin.server.op.standard;
 
-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;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.server.Context;
 import org.apache.tinkerpop.gremlin.server.OpProcessor;
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 1136046..5749255 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
@@ -21,11 +21,11 @@
 import com.codahale.metrics.Timer;
 import io.netty.channel.ChannelException;
 import io.netty.channel.ChannelHandlerContext;
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
-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;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.jsr223.JavaTranslator;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.Failure;
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializer.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializer.java
index 81b3662..fe6cdbf 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializer.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializer.java
@@ -20,10 +20,10 @@
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
-import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
-import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.ser.MessageTextSerializer;
+import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
 
 import java.util.List;
 import java.util.Objects;
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TraverserIterator.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TraverserIterator.java
index 8ea6e55..ade1e82 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TraverserIterator.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TraverserIterator.java
@@ -21,7 +21,6 @@
 import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.HaltedTraverserStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
 
@@ -33,17 +32,12 @@
 public class TraverserIterator implements Iterator<Object> {
 
     private final Traversal.Admin traversal;
-    private final HaltedTraverserStrategy haltedTraverserStrategy;
     private final TraverserSet bulker = new TraverserSet();
     private final int barrierSize;
 
     public TraverserIterator(final Traversal.Admin traversal) {
         this.traversal = traversal;
         this.barrierSize = traversal.getTraverserRequirements().contains(TraverserRequirement.ONE_BULK) ? 1 : 1000;
-        this.haltedTraverserStrategy = traversal.getStrategies().getStrategy(HaltedTraverserStrategy.class).orElse(
-                Boolean.valueOf(System.getProperty("is.testing", "false")) ?
-                        HaltedTraverserStrategy.detached() :
-                        HaltedTraverserStrategy.reference());
     }
 
     public Traversal.Admin getTraversal() {
@@ -61,7 +55,7 @@
     public Object next() {
         if (this.bulker.isEmpty())
             this.fillBulker();
-        final Traverser.Admin t = this.haltedTraverserStrategy.halt(this.bulker.remove());
+        final Traverser.Admin t = this.bulker.remove();
         return new DefaultRemoteTraverser<>(t.get(), t.bulk());
     }
 
diff --git a/gremlin-server/src/main/static/LICENSE b/gremlin-server/src/main/static/LICENSE
index dd3f492..7250972 100644
--- a/gremlin-server/src/main/static/LICENSE
+++ b/gremlin-server/src/main/static/LICENSE
@@ -217,6 +217,7 @@
      minlog (com.esotericsoftware:minlog:1.3.0 - https://github.com/EsotericSoftware/minlog)
        - shaded in gremlin-shaded to org.apache.tinkerpop.shaded.minlog
        - for details, see licenses/minlog
+     treelayout (org.abego.treelayout:org.abego.treelayout.core:1.0.3 - http://treelayout.sourceforge.net/) - for details, see licenses/treelayout
 
 ========================================================================
 MIT Licenses
diff --git a/gremlin-server/src/main/static/NOTICE b/gremlin-server/src/main/static/NOTICE
index 5731302..65be68b 100644
--- a/gremlin-server/src/main/static/NOTICE
+++ b/gremlin-server/src/main/static/NOTICE
@@ -5,15 +5,10 @@
 The Apache Software Foundation (http://www.apache.org/).
 
 ------------------------------------------------------------------------
-Apache Groovy 2.5.22 (AL ASF)
+Apache Groovy 4.0.9 (AL ASF)
 ------------------------------------------------------------------------
-This product includes/uses ANTLR (http://www.antlr2.org/)
-developed by Terence Parr 1989-2006
-
-This product bundles icons from the famfamfam.com silk icons set
-http://www.famfamfam.com/lab/icons/silk/
-Licensed under the Creative Commons Attribution Licence v2.5
-http://creativecommons.org/licenses/by/2.5/
+This product includes/uses ANTLR4 (https://github.com/antlr/antlr4)
+Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
 
 ------------------------------------------------------------------------
 Apache Ivy 2.3.0 (AL ASF)
@@ -42,7 +37,7 @@
    (Apache license)
 
 ------------------------------------------------------------------------
-Jackson-Databind 2.14.0 and Jackson-Core (Included through gremlin-shaded)
+Jackson-Databind 2.14.0 and Jackson-Core - shaded in gremlin-shaded to org.apache.tinkerpop.shaded.jackson
 ------------------------------------------------------------------------
 It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has
 been in development since 2007.
@@ -73,6 +68,6 @@
 Copyright 2014 The Netty Project
 
 ------------------------------------------------------------------------
-Objenesis 2.4 (Included through gremlin-shaded)
+Objenesis 3.3 - shaded in gremlin-shaded to org.apache.tinkerpop.shaded.objenesis
 ------------------------------------------------------------------------
-Copyright 2006-2016 Joe Walnes, Henri Tremblay, Leonardo Mesquita
+Copyright 2006-2022 Joe Walnes, Henri Tremblay, Leonardo Mesquita
diff --git a/gremlin-server/src/main/static/licenses/treelayout b/gremlin-server/src/main/static/licenses/treelayout
new file mode 100644
index 0000000..e92280d
--- /dev/null
+++ b/gremlin-server/src/main/static/licenses/treelayout
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2011, abego Software GmbH, Germany (http://www.abego.org)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+* Neither the name of the copyright holder nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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 3c4c777..d125a3d 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
@@ -22,10 +22,11 @@
 import ch.qos.logback.classic.Logger;
 import io.netty.handler.codec.CorruptedFrameException;
 import nl.altindag.log.LogCaptor;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.driver.exception.ConnectionException;
 import org.apache.tinkerpop.gremlin.driver.exception.NoHostAvailableException;
-import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
+import org.apache.tinkerpop.gremlin.util.ser.Serializers;
 import org.apache.tinkerpop.gremlin.server.AbstractGremlinServerIntegrationTest;
 import org.apache.tinkerpop.gremlin.server.TestClientFactory;
 import org.hamcrest.core.Is;
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 89bb7a0..49c9134 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
@@ -24,7 +24,7 @@
 import org.apache.tinkerpop.gremlin.TestHelper;
 import org.apache.tinkerpop.gremlin.driver.Client;
 import org.apache.tinkerpop.gremlin.driver.Cluster;
-import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
+import org.apache.tinkerpop.gremlin.util.ser.Serializers;
 import org.apache.tinkerpop.gremlin.process.computer.Computer;
 import org.apache.tinkerpop.gremlin.process.remote.RemoteConnection;
 import org.apache.tinkerpop.gremlin.structure.RemoteGraph;
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 aabd65b..2124721 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
@@ -20,7 +20,7 @@
 package org.apache.tinkerpop.gremlin.driver.remote;
 
 import org.apache.tinkerpop.gremlin.GraphProvider;
-import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
+import org.apache.tinkerpop.gremlin.util.ser.Serializers;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.tinkergraph.process.computer.TinkerGraphComputer;
 
@@ -56,6 +56,10 @@
         method = "g_VX1X_V_valuesXnameX",
         reason = "Mid-traversal V()/E() is currently not supported on GraphComputer")
 @Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeTest",
+        method = "*",
+        reason = "Mid-traversal V()/E() is currently not supported on GraphComputer")
+@Graph.OptOut(
         test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectTest",
         method = "*",
         reason = "The inject() step is not supported by GraphComputer")
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryRemoteGraphProvider.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryRemoteGraphProvider.java
index a5f8f88..09c3b64 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryRemoteGraphProvider.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryRemoteGraphProvider.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.driver.remote;
 
-import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
+import org.apache.tinkerpop.gremlin.util.ser.Serializers;
 
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)
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 4736ae9..405103f 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
@@ -20,7 +20,7 @@
 package org.apache.tinkerpop.gremlin.driver.remote;
 
 import org.apache.tinkerpop.gremlin.GraphProvider;
-import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
+import org.apache.tinkerpop.gremlin.util.ser.Serializers;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.tinkergraph.process.computer.TinkerGraphComputer;
 
@@ -56,6 +56,10 @@
         method = "g_VX1X_V_valuesXnameX",
         reason = "Mid-traversal V()/E() is currently not supported on GraphComputer")
 @Graph.OptOut(
+        test = "org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeTest",
+        method = "*",
+        reason = "Mid-traversal V()/E() is currently not supported on GraphComputer")
+@Graph.OptOut(
         test = "org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectTest",
         method = "*",
         reason = "The inject() step is not supported by GraphComputer")
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONRemoteGraphProvider.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONRemoteGraphProvider.java
index 61debb2..09b65d6 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONRemoteGraphProvider.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphSONRemoteGraphProvider.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.driver.remote;
 
-import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
+import org.apache.tinkerpop.gremlin.util.ser.Serializers;
 
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/ContextTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/ContextTest.java
index 56cb718..2092713 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/ContextTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/ContextTest.java
@@ -20,9 +20,10 @@
 
 import io.netty.channel.ChannelHandlerContext;
 import nl.altindag.log.LogCaptor;
-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.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.server.handler.Frame;
 import org.junit.AfterClass;
 import org.junit.Before;
@@ -38,6 +39,7 @@
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertEquals;
 
 @RunWith(Parameterized.class)
 public class ContextTest {
@@ -175,4 +177,34 @@
         Mockito.verify(frame, Mockito.times(1)).tryRelease();
         Mockito.verify(ctx, Mockito.times(1)).flush();
     }
+
+    @Test
+    public void shouldParseParametersFromScriptRequest()
+    {
+        final ChannelHandlerContext ctx = Mockito.mock(ChannelHandlerContext.class);
+        final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
+                .addArg(Tokens.ARGS_GREMLIN, "g.with('evaluationTimeout', 1000).with(true).with('materializeProperties', 'tokens').V().out('knows')")
+                .create();
+        final Settings settings = new Settings();
+        final Context context = new Context(request, ctx, settings, null, null, null);
+
+        assertEquals(1000, context.getRequestTimeout());
+        assertEquals("tokens", context.getMaterializeProperties());
+    }
+
+    @Test
+    public void shouldSkipInvalidMaterializePropertiesParameterFromScriptRequest()
+    {
+        final ChannelHandlerContext ctx = Mockito.mock(ChannelHandlerContext.class);
+        final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
+                .addArg(Tokens.ARGS_GREMLIN,
+                        "g.with('evaluationTimeout', 1000).with(true).with('materializeProperties', 'some-invalid-value').V().out('knows')")
+                .create();
+        final Settings settings = new Settings();
+        final Context context = new Context(request, ctx, settings, null, null, null);
+
+        assertEquals(1000, context.getRequestTimeout());
+        // "all" is default value
+        assertEquals("all", context.getMaterializeProperties());
+    }
 }
\ No newline at end of file
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 72a529e..ad380f9 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
@@ -28,16 +28,16 @@
 import org.apache.tinkerpop.gremlin.driver.RequestOptions;
 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.util.Tokens;
 import org.apache.tinkerpop.gremlin.driver.exception.ConnectionException;
 import org.apache.tinkerpop.gremlin.driver.exception.NoHostAvailableException;
 import org.apache.tinkerpop.gremlin.driver.exception.ResponseException;
 import org.apache.tinkerpop.gremlin.driver.handler.WebSocketClientHandler;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.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.Serializers;
+import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
+import org.apache.tinkerpop.gremlin.util.ser.Serializers;
 import org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
@@ -45,7 +45,6 @@
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.io.Storage;
 import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
-import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceVertex;
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
 import org.apache.tinkerpop.gremlin.util.TimeUtil;
 import org.apache.tinkerpop.gremlin.util.function.FunctionUtils;
@@ -54,7 +53,6 @@
 import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
@@ -1000,7 +998,7 @@
             final List<Result> r = client.submit("TinkerFactory.createModern().traversal().V(1)").all().join();
             assertEquals(1, r.size());
 
-            final Vertex v = r.get(0).get(ReferenceVertex.class);
+            final Vertex v = r.get(0).get(DetachedVertex.class);
             assertEquals(1, v.id());
             assertEquals("person", v.label());
         } finally {
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinResultSetIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinResultSetIntegrateTest.java
index 5500315..2786750 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinResultSetIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinResultSetIntegrateTest.java
@@ -20,12 +20,8 @@
 
 import org.apache.tinkerpop.gremlin.driver.Client;
 import org.apache.tinkerpop.gremlin.driver.Cluster;
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
 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.ser.GraphBinaryMessageSerializerV1;
-import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
@@ -36,14 +32,16 @@
 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 import org.apache.tinkerpop.gremlin.structure.io.IoTest;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryMapper;
-import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceEdge;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty;
 import org.apache.tinkerpop.gremlin.structure.util.reference.ReferencePath;
 import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceProperty;
-import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceVertex;
-import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceVertexProperty;
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0;
-import org.apache.tinkerpop.shaded.kryo.Kryo;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
+import org.apache.tinkerpop.gremlin.util.ser.Serializers;
 import org.hamcrest.CoreMatchers;
 import org.junit.After;
 import org.junit.Before;
@@ -52,7 +50,6 @@
 import org.junit.runners.Parameterized;
 
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -147,21 +144,21 @@
     public void shouldHandleVertexResult() throws Exception {
         final ResultSet results = client.submit("gmodern.V(1).next()");
         final Vertex v = results.all().get().get(0).getVertex();
-        assertThat(v, instanceOf(ReferenceVertex.class));
+        assertThat(v, instanceOf(DetachedVertex.class));
     }
 
     @Test
     public void shouldHandleVertexPropertyResult() throws Exception {
         final ResultSet results = client.submit("gmodern.V().properties('name').next()");
         final VertexProperty<String> v = results.all().get().get(0).getVertexProperty();
-        assertThat(v, instanceOf(ReferenceVertexProperty.class));
+        assertThat(v, instanceOf(DetachedVertexProperty.class));
     }
 
     @Test
     public void shouldHandleEdgeResult() throws Exception {
         final ResultSet results = client.submit("gmodern.E().next()");
         final Edge e = results.all().get().get(0).getEdge();
-        assertThat(e, instanceOf(ReferenceEdge.class));
+        assertThat(e, instanceOf(DetachedEdge.class));
     }
 
     @Test
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthIntegrateTest.java
index 63090b3..67ab771 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthIntegrateTest.java
@@ -35,7 +35,7 @@
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
 
-import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
+import org.apache.tinkerpop.gremlin.util.ser.Serializers;
 
 import static org.hamcrest.CoreMatchers.startsWith;
 import static org.hamcrest.MatcherAssert.assertThat;
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 9a737d2..2a534bf 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
@@ -21,10 +21,10 @@
 import org.apache.tinkerpop.gremlin.util.ExceptionHelper;
 import org.apache.tinkerpop.gremlin.driver.Client;
 import org.apache.tinkerpop.gremlin.driver.Cluster;
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
 import org.apache.tinkerpop.gremlin.driver.exception.ResponseException;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
 import org.apache.tinkerpop.gremlin.server.auth.Krb5Authenticator;
 import org.ietf.jgss.GSSException;
 import org.junit.Test;
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthzIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthzIntegrateTest.java
index b3069fd..871ce4f 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthzIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthzIntegrateTest.java
@@ -27,7 +27,7 @@
 import org.apache.tinkerpop.gremlin.driver.Client;
 import org.apache.tinkerpop.gremlin.driver.Cluster;
 import org.apache.tinkerpop.gremlin.driver.exception.ResponseException;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 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;
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 4f44158..b52bda0 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
@@ -20,13 +20,13 @@
 
 import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.http.HttpHeaders;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0;
-import org.apache.tinkerpop.gremlin.driver.Tokens;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV2d0;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0;
-import org.apache.tinkerpop.gremlin.driver.ser.SerTokens;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
+import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV1d0;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV2d0;
+import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0;
+import org.apache.tinkerpop.gremlin.util.ser.SerTokens;
 import org.apache.tinkerpop.gremlin.server.auth.SimpleAuthenticator;
 import org.apache.tinkerpop.gremlin.server.channel.HttpChannelizer;
 import org.apache.http.Consts;
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 55dbb4e..e76d748 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
@@ -33,13 +33,13 @@
 import org.apache.tinkerpop.gremlin.driver.Cluster;
 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.util.Tokens;
 import org.apache.tinkerpop.gremlin.driver.exception.ResponseException;
-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.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteConnection;
-import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
+import org.apache.tinkerpop.gremlin.util.ser.Serializers;
 import org.apache.tinkerpop.gremlin.driver.simple.SimpleClient;
 import org.apache.tinkerpop.gremlin.driver.UserAgent;
 import org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine;
@@ -93,7 +93,7 @@
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
-import static org.apache.tinkerpop.gremlin.driver.Tokens.ARGS_EVAL_TIMEOUT;
+import static org.apache.tinkerpop.gremlin.util.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;
@@ -967,7 +967,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 = ExceptionHelper.getRootCause(re);
@@ -1133,7 +1133,7 @@
 
     @Test
     public void shouldProvideBetterExceptionForMethodCodeTooLarge() {
-        final int numberOfParameters = 4000;
+        final int numberOfParameters = 6000;
         final Map<String,Object> b = new HashMap<>();
 
         // generate a script with a ton of bindings usage to generate a "code too large" exception
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSerializationIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSerializationIntegrateTest.java
new file mode 100644
index 0000000..f888d5a
--- /dev/null
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSerializationIntegrateTest.java
@@ -0,0 +1,227 @@
+/*
+ * 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.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.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.util.iterator.IteratorUtils;
+import org.apache.tinkerpop.gremlin.util.ser.AbstractMessageSerializer;
+import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
+import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV2d0;
+import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(Parameterized.class)
+public class GremlinServerSerializationIntegrateTest extends AbstractGremlinServerIntegrationTest {
+
+    private AbstractMessageSerializer serializer;
+    private Cluster cluster = null;
+    private Client client = null;
+    private GraphTraversalSource g = null;
+
+    public GremlinServerSerializationIntegrateTest(AbstractMessageSerializer serializer) {
+        this.serializer = serializer;
+    }
+
+    @Parameterized.Parameters
+    public static Collection serializers() {
+        return Arrays.asList(new Object[][]{
+                {new GraphBinaryMessageSerializerV1()},
+                {new GraphSONMessageSerializerV3d0()},
+                {new GraphSONMessageSerializerV2d0()}
+        });
+    }
+
+    @Before
+    public void openConnection() {
+        cluster = TestClientFactory.build().serializer(serializer).create();
+        client = cluster.connect();
+
+        // VertexProperty related test tun on crew graph
+        final String remoteTraversalSourceName = name.getMethodName().contains("VertexProperty") ? "gcrew" : "gmodern";
+
+        g = AnonymousTraversalSource.traversal().withRemote(
+                DriverRemoteConnection.using(cluster, remoteTraversalSourceName));
+    }
+
+    @After
+    public void closeConnection() {
+        if (cluster != null) cluster.close();
+    }
+
+    @Test
+    public void shouldDeserializeVertexPropertiesForScripts() {
+        final Vertex vertex = client.submit("gmodern.V(1)").one().getVertex();
+
+        assertVertexWithProperties(vertex);
+    }
+
+    @Test
+    public void shouldSkipVertexPropertiesForScripts() {
+        final Vertex vertex = client.submit("gmodern.with('materializeProperties', 'tokens').V(1)").one().getVertex();
+
+        assertVertexWithoutProperties(vertex);
+    }
+
+    @Test
+    public void shouldDeserializeVertexPropertiesForBytecode() {
+        final Vertex vertex = g.V(1).next();
+
+        assertVertexWithProperties(vertex);
+    }
+
+    @Test
+    public void shouldSkipVertexPropertiesForBytecode() {
+        final Vertex vertex = g.with("materializeProperties", "tokens").V(1).next();
+
+        assertVertexWithoutProperties(vertex);
+    }
+
+    @Test
+    public void shouldDeserializeEdgePropertiesForScripts() {
+        final Edge edge = client.submit("gmodern.E(7)").one().getEdge();
+
+        assertEdgeWithProperties(edge);
+    }
+
+    @Test
+    public void shouldSkipEdgePropertiesForScripts() {
+        final Edge edge = client.submit("gmodern.with('materializeProperties', 'tokens').E(7)").one().getEdge();
+
+        assertEdgeWithoutProperties(edge);
+    }
+
+    @Test
+    public void shouldDeserializeEdgePropertiesForBytecode() {
+        final Edge edge = g.E(7).next();
+
+        assertEdgeWithProperties(edge);
+    }
+
+    @Test
+    public void shouldSkipEdgePropertiesForBytecode() {
+        final Edge edge = g.with("materializeProperties", "tokens").E(7).next();
+
+        assertEdgeWithoutProperties(edge);
+    }
+
+    @Test
+    public void shouldDeserializeVertexPropertyPropertiesForScripts() {
+        final Vertex vertex = client.submit("gcrew.V(7)").one().getVertex();
+
+        assertVertexWithVertexProperties(vertex);
+    }
+
+    @Test
+    public void shouldSkipVertexPropertyPropertiesForScripts() {
+        final Vertex vertex = client.submit("gcrew.with('materializeProperties', 'tokens').V(7)").one().getVertex();
+
+        assertVertexWithoutVertexProperties(vertex);
+    }
+
+    @Test
+    public void shouldDeserializeVertexPropertyPropertiesForBytecode() {
+        final Vertex vertex = g.V(7).next();
+
+        assertVertexWithVertexProperties(vertex);
+    }
+
+    @Test
+    public void shouldSkipVertexPropertyPropertiesForBytecode() {
+        final Vertex vertex = g.with("materializeProperties", "tokens").V(7).next();
+
+        assertVertexWithoutVertexProperties(vertex);
+    }
+
+    // asserted vertex 7 from crew graph
+    private void assertVertexWithVertexProperties(final Vertex vertex) {
+        assertEquals(7, vertex.id());
+        assertEquals("person", vertex.label());
+
+        assertEquals(4, IteratorUtils.count(vertex.properties()));
+        assertEquals(3, IteratorUtils.count(vertex.properties("location")));
+        final VertexProperty vertexProperty = vertex.properties("location").next();
+        assertEquals("centreville", vertexProperty.value());
+        assertEquals(2, IteratorUtils.count(vertexProperty.properties()));
+        final Property vertexPropertyPropertyStartTime = vertexProperty.property("startTime");
+        assertEquals(1990, vertexPropertyPropertyStartTime.value());
+        final Property vertexPropertyPropertyEndTime = vertexProperty.property("endTime");
+        assertEquals(2000, vertexPropertyPropertyEndTime.value());
+    }
+
+    // asserted vertex 7 from crew graph
+    private void assertVertexWithoutVertexProperties(final Vertex vertex) {
+        assertEquals(7, vertex.id());
+        assertEquals("person", vertex.label());
+
+        assertEquals(0, IteratorUtils.count(vertex.properties()));
+    }
+
+    // asserted vertex 1 from modern graph
+    private void assertVertexWithoutProperties(final Vertex vertex) {
+        assertEquals(1, vertex.id());
+        assertEquals("person", vertex.label());
+
+        assertEquals(Collections.emptyIterator(), vertex.properties());
+    }
+
+    // asserted vertex 1 from modern graph
+    private void assertVertexWithProperties(final Vertex vertex) {
+        assertEquals(1, vertex.id());
+        assertEquals("person", vertex.label());
+
+        assertEquals(2, IteratorUtils.count(vertex.properties()));
+        assertEquals("marko", vertex.property("name").value());
+        assertEquals(29, vertex.property("age").value());
+    }
+
+    // asserted edge 7 from modern graph
+    private void assertEdgeWithoutProperties(final Edge edge) {
+        assertEquals(7, edge.id());
+        assertEquals("knows", edge.label());
+
+        assertEquals(Collections.emptyIterator(), edge.properties());
+    }
+
+    // asserted edge 7 from modern graph
+    private void assertEdgeWithProperties(final Edge edge) {
+        assertEquals(7, edge.id());
+        assertEquals("knows", edge.label());
+
+        assertEquals(1, IteratorUtils.count(edge.properties()));
+        assertEquals(0.5, edge.property("weight").value());
+    }
+}
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 b951d88..61ab6f8 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
@@ -28,11 +28,11 @@
 import org.apache.tinkerpop.gremlin.driver.Cluster;
 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.util.Tokens;
 import org.apache.tinkerpop.gremlin.driver.exception.ResponseException;
-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.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.driver.simple.SimpleClient;
 import org.apache.tinkerpop.gremlin.server.channel.UnifiedChannelizer;
 import org.apache.tinkerpop.gremlin.server.op.session.Session;
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 06ec8c9..09a6b14 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
@@ -38,7 +38,7 @@
     }
 
     public static Cluster.Builder build(final String address) {
-        return Cluster.build(address).port(45940);
+        return Cluster.build(address).port(PORT);
     }
 
     public static Cluster open() {
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/authz/AllowListAuthorizer.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/authz/AllowListAuthorizer.java
index 7d4c604..962fa2c 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/authz/AllowListAuthorizer.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/authz/AllowListAuthorizer.java
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.server.authz;
 
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.verification.VertexProgramRestrictionStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
@@ -142,7 +142,7 @@
      * {@link AuthorizationException} if this is not the case.
      *
      * @param user {@link AuthenticatedUser} that needs authorization.
-     * @param msg {@link RequestMessage} in which the {@link org.apache.tinkerpop.gremlin.driver.Tokens}.ARGS_GREMLIN argument can contain an arbitrary succession of script statements.
+     * @param msg {@link RequestMessage} in which the {@link org.apache.tinkerpop.gremlin.util.Tokens}.ARGS_GREMLIN argument can contain an arbitrary succession of script statements.
      */
     public void authorize(final AuthenticatedUser user, final RequestMessage msg) throws AuthorizationException {
         if (!usernamesSandbox.contains(user.getName())) {
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/authz/AuthorizerTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/authz/AuthorizerTest.java
index 1b30c24..b8ec8b7 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/authz/AuthorizerTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/authz/AuthorizerTest.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.server.authz;
 
-import org.apache.tinkerpop.gremlin.driver.Tokens;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.verification.VertexProgramRestrictionStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/notifications/GraphManagerNotificationsTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/notifications/GraphManagerNotificationsTest.java
index 6d6f2d1..34fbd99 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/notifications/GraphManagerNotificationsTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/notifications/GraphManagerNotificationsTest.java
@@ -22,7 +22,7 @@
 import org.apache.tinkerpop.gremlin.driver.Client;
 import org.apache.tinkerpop.gremlin.driver.Cluster;
 import org.apache.tinkerpop.gremlin.driver.RequestOptions;
-import org.apache.tinkerpop.gremlin.driver.Tokens;
+import org.apache.tinkerpop.gremlin.util.Tokens;
 import org.apache.tinkerpop.gremlin.server.AbstractGremlinServerIntegrationTest;
 import org.apache.tinkerpop.gremlin.server.Settings;
 import org.apache.tinkerpop.gremlin.server.TestClientFactory;
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/notifications/ProviderGraphManagerHelper.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/notifications/ProviderGraphManagerHelper.java
index 211d2aa..94bd6fb 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/notifications/ProviderGraphManagerHelper.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/notifications/ProviderGraphManagerHelper.java
@@ -24,7 +24,7 @@
 import java.util.List;
 import java.util.Map;
 
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.server.Settings;
 import org.apache.tinkerpop.gremlin.server.util.DefaultGraphManager;
 
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 aa3fd73..42852f4 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,10 +19,10 @@
 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;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.groovy.engine.GremlinExecutor;
 import org.apache.tinkerpop.gremlin.server.Context;
 import org.apache.tinkerpop.gremlin.server.Settings;
@@ -38,7 +38,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.Matchers.anyString;
+import static org.mockito.ArgumentMatchers.anyString;
 
 public class AbstractEvalOpProcessorTest {
 
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/op/AbstractOpProcessorTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/op/AbstractOpProcessorTest.java
index eaba1c6..0117562 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/op/AbstractOpProcessorTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/op/AbstractOpProcessorTest.java
@@ -18,9 +18,9 @@
  */
 package org.apache.tinkerpop.gremlin.server.op;
 
-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.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.server.Context;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializerTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializerTest.java
index 803d149..b88daaf 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializerTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializerTest.java
@@ -19,7 +19,7 @@
 package org.apache.tinkerpop.gremlin.server.util;
 
 import io.netty.buffer.ByteBufAllocator;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
 import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
 import org.junit.Test;
 
diff --git a/gremlin-server/src/test/resources/conf/remote-objects.yaml b/gremlin-server/src/test/resources/conf/remote-objects.yaml
index b32ba79..f9043f0 100644
--- a/gremlin-server/src/test/resources/conf/remote-objects.yaml
+++ b/gremlin-server/src/test/resources/conf/remote-objects.yaml
@@ -29,4 +29,4 @@
 
 hosts: [localhost]
 port: 45940
-serializer: {  className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1 }
\ No newline at end of file
+serializer: {  className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1 }
\ No newline at end of file
diff --git a/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-integration.yaml b/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-integration.yaml
index 97b8157..34884ae 100644
--- a/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-integration.yaml
+++ b/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-integration.yaml
@@ -48,11 +48,11 @@
                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.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 }}
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3d0] }}
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV2d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV2d0] }}
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerGremlinV1d0, config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV1d0] }}
+  - { className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1 }
+  - { className: org.apache.tinkerpop.gremlin.util.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: {}}
diff --git a/gremlin-server/src/test/scripts/generate-all.groovy b/gremlin-server/src/test/scripts/generate-all.groovy
index a44786d..88ca00e 100644
--- a/gremlin-server/src/test/scripts/generate-all.groovy
+++ b/gremlin-server/src/test/scripts/generate-all.groovy
@@ -38,10 +38,6 @@
     allowSetOfIdManager = { graph, idManagerFieldName, idManager ->
         java.lang.reflect.Field idManagerField = graph.class.getDeclaredField(idManagerFieldName)
         idManagerField.setAccessible(true)
-        java.lang.reflect.Field modifiersField = java.lang.reflect.Field.class.getDeclaredField("modifiers")
-        modifiersField.setAccessible(true)
-        modifiersField.setInt(idManagerField, modifiersField.getModifiers() & ~java.lang.reflect.Modifier.FINAL)
-
         idManagerField.set(graph, idManager)
     }
 
@@ -60,24 +56,24 @@
 ] as LifeCycleHook]
 
 // add default TraversalSource instances for each graph instance
-globals << [gclassic : traversal().withEmbedded(classic).withStrategies(ReferenceElementStrategy)]
-globals << [gmodern : traversal().withEmbedded(modern).withStrategies(ReferenceElementStrategy)]
-globals << [g : traversal().withEmbedded(graph).withStrategies(ReferenceElementStrategy)]
-globals << [gcrew : traversal().withEmbedded(crew).withStrategies(ReferenceElementStrategy)]
-globals << [ggraph : traversal().withEmbedded(graph).withStrategies(ReferenceElementStrategy)]
-globals << [ggrateful : traversal().withEmbedded(grateful).withStrategies(ReferenceElementStrategy)]
-globals << [gsink : traversal().withEmbedded(sink).withStrategies(ReferenceElementStrategy)]
+globals << [gclassic : traversal().withEmbedded(classic)]
+globals << [gmodern : traversal().withEmbedded(modern)]
+globals << [g : traversal().withEmbedded(graph)]
+globals << [gcrew : traversal().withEmbedded(crew)]
+globals << [ggraph : traversal().withEmbedded(graph)]
+globals << [ggrateful : traversal().withEmbedded(grateful)]
+globals << [gsink : traversal().withEmbedded(sink)]
 
 // dynamically detect existence of gtx as it may or may not be present depending on the -DincludeNeo4j
 // and the configuration of the particular server instance. with docker/gremlin-server.sh the neo4j
 // "tx" configuration is already present and will therefore be enabled.
 def dynamicGtx = context.getBindings(javax.script.ScriptContext.GLOBAL_SCOPE)["tx"]
 if (dynamicGtx != null)
-    globals << [gtx : traversal().withEmbedded(dynamicGtx).withStrategies(ReferenceElementStrategy)]
+    globals << [gtx : traversal().withEmbedded(dynamicGtx)]
 
 // dynamically detect existence of gimmutable as it is only used in gremlin-go testing suite
 def dynamicGimmutable = context.getBindings(javax.script.ScriptContext.GLOBAL_SCOPE)["immutable"]
 if (dynamicGimmutable != null)
-    globals << [gimmutable : traversal().withEmbedded(dynamicGimmutable).withStrategies(ReferenceElementStrategy)]
+    globals << [gimmutable : traversal().withEmbedded(dynamicGimmutable)]
 
 globals
diff --git a/gremlin-shaded/pom.xml b/gremlin-shaded/pom.xml
index 72932e3..cd7ad0c 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.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-shaded</artifactId>
     <name>Apache TinkerPop :: Gremlin Shaded</name>
diff --git a/gremlin-shaded/src/main/static/NOTICE b/gremlin-shaded/src/main/static/NOTICE
index 34f724b..9972866 100644
--- a/gremlin-shaded/src/main/static/NOTICE
+++ b/gremlin-shaded/src/main/static/NOTICE
@@ -5,27 +5,13 @@
 The Apache Software Foundation (http://www.apache.org/).
 
 ------------------------------------------------------------------------
-Jackson-Databind 2.14.0 and Jackson-Core
+Jackson-Databind 2.14.0 and Jackson-Core - shaded in gremlin-shaded to org.apache.tinkerpop.shaded.jackson
 ------------------------------------------------------------------------
-# Jackson JSON processor
-
-Jackson is a high-performance, Free/Open Source JSON processing library.
 It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has
 been in development since 2007.
 It is currently developed by a community of developers.
 
-## Licensing
-
-Jackson 2.x core and extension components are licensed under Apache License 2.0
-To find the details that apply to this artifact see the accompanying LICENSE file.
-
-## Credits
-
-A list of contributors may be found from CREDITS(-2.x) file, which is included
-in some artifacts (usually source distributions); but is always available
-from the source code management (SCM) system project uses.
-
 ------------------------------------------------------------------------
-Objenesis 2.4
+Objenesis 3.3 - shaded in gremlin-shaded to org.apache.tinkerpop.shaded.objenesis
 ------------------------------------------------------------------------
-Copyright 2006-2016 Joe Walnes, Henri Tremblay, Leonardo Mesquita
+Copyright 2006-2022 Joe Walnes, Henri Tremblay, Leonardo Mesquita
diff --git a/gremlin-test/pom.xml b/gremlin-test/pom.xml
index b13c2ea..40caddf 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.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-test</artifactId>
     <name>Apache TinkerPop :: Gremlin Test</name>
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeTest.java
new file mode 100644
index 0000000..61ca5f6
--- /dev/null
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/EdgeTest.java
@@ -0,0 +1,159 @@
+/*
+ * 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.FeatureRequirement;
+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.P;
+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.Graph;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.GRATEFUL;
+import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Valentyn Kahamlyk
+ */
+@RunWith(GremlinProcessRunner.class)
+public abstract class EdgeTest extends AbstractGremlinProcessTest {
+
+    public abstract Traversal<Vertex, Edge> get_g_V_EX11X(final Object e11Id);
+
+    public abstract Traversal<Edge, Edge> get_g_EX11X_E(final Object e11Id);
+
+    public abstract Traversal<Vertex, Edge> get_g_V_EXnullX();
+
+    public abstract Traversal<Integer, Edge> get_g_injectX1X_EX11_nullX(final Object e11Id);
+
+    public abstract Traversal<Integer, Edge> get_g_injectX1X_coalesceXEX_hasLabelXtestsX_addEXtestsX_from_V_hasXnameX_XjoshXX_toXV_hasXnameX_XvadasXXX();
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_EX11X() {
+        final Object edgeId = convertToEdgeId("josh", "created", "lop");
+        final Traversal<Vertex, Edge> traversal = get_g_V_EX11X(edgeId);
+        printTraversalForm(traversal);
+        int counter = 0;
+        final Set<Edge> edges = new HashSet<>();
+        while (traversal.hasNext()) {
+            counter++;
+            edges.add(traversal.next());
+        }
+        assertEquals(6, edges.size());
+        assertEquals(6, counter);
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_EX11X_E() {
+        final Object edgeId = convertToEdgeId("josh", "created", "lop");
+        final Traversal<Edge, Edge> traversal = get_g_EX11X_E(edgeId);
+        printTraversalForm(traversal);
+        int counter = 0;
+        final Set<Edge> edges = new HashSet<>();
+        while (traversal.hasNext()) {
+            counter++;
+            edges.add(traversal.next());
+        }
+        assertEquals(6, edges.size());
+        assertEquals(6, counter);
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_EXnullX() {
+        final Traversal<Vertex, Edge> traversal = get_g_V_EXnullX();
+        printTraversalForm(traversal);
+        int counter = 0;
+        final Set<Edge> edges = new HashSet<>();
+        while (traversal.hasNext()) {
+            counter++;
+            edges.add(traversal.next());
+        }
+        assertEquals(0, edges.size());
+        assertEquals(0, counter);
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_injectX1X_EX11_nullX() {
+        final Object edgeId = convertToEdgeId("josh", "created", "lop");
+        final Traversal<Integer, Edge> traversal = get_g_injectX1X_EX11_nullX(edgeId);
+        printTraversalForm(traversal);
+        int counter = 0;
+        final Set<Edge> edges = new HashSet<>();
+        while (traversal.hasNext()) {
+            counter++;
+            edges.add(traversal.next());
+        }
+        assertEquals(1, edges.size());
+        assertEquals(1, counter);
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_injectX1X_coalesceXEX_hasLabelXtestsX_addEXtestsX_from_V_hasXnameX_XjoshXX_toXV_hasXnameX_XvadasXXX() {
+        final Traversal<Integer, Edge> traversal = get_g_injectX1X_coalesceXEX_hasLabelXtestsX_addEXtestsX_from_V_hasXnameX_XjoshXX_toXV_hasXnameX_XvadasXXX();
+        printTraversalForm(traversal);
+        int counter = 0;
+        final Set<Edge> edges = new HashSet<>();
+        while (traversal.hasNext()) {
+            counter++;
+            edges.add(traversal.next());
+        }
+        assertEquals(1, edges.size());
+        assertEquals(1, counter);
+    }
+
+    public static class Traversals extends EdgeTest {
+
+        @Override
+        public Traversal<Vertex, Edge> get_g_V_EX11X(final Object e11Id) { return g.V().E(e11Id); }
+
+        @Override
+        public Traversal<Edge, Edge> get_g_EX11X_E(final Object e11Id) {
+            return g.E(e11Id).E();
+        }
+
+        @Override
+        public Traversal<Vertex, Edge> get_g_V_EXnullX() { return g.V().E(null); }
+
+        @Override
+        public Traversal<Integer, Edge> get_g_injectX1X_EX11_nullX(final Object e11Id) { return g.inject(1).E(e11Id,null); }
+
+        @Override
+        public Traversal<Integer, Edge> get_g_injectX1X_coalesceXEX_hasLabelXtestsX_addEXtestsX_from_V_hasXnameX_XjoshXX_toXV_hasXnameX_XvadasXXX() {
+            return g.inject(1).coalesce(__.E().hasLabel("tests"), __.addE("tests").from(__.V().has("name","josh")).to(__.V().has("name","vadas")));
+        }
+    }
+}
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature
new file mode 100644
index 0000000..f3d9232
--- /dev/null
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/Edge.feature
@@ -0,0 +1,99 @@
+# 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.
+
+@StepClassMap @StepE
+Feature: Step - E()
+
+  Scenario: g_V_EX11X
+    Given the modern graph
+    And using the parameter eid11 defined as "e[josh-created->lop].id"
+    And the traversal of
+      """
+      g.V().E(eid11)
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | e[josh-created->lop] |
+      | e[josh-created->lop] |
+      | e[josh-created->lop] |
+      | e[josh-created->lop] |
+      | e[josh-created->lop] |
+      | e[josh-created->lop] |
+
+  Scenario: g_EX11X_E
+    Given the modern graph
+    And using the parameter eid11 defined as "e[josh-created->lop].id"
+    And the traversal of
+      """
+      g.E(eid11).E()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | e[marko-created->lop] |
+      | e[marko-knows->josh] |
+      | e[marko-knows->vadas] |
+      | e[peter-created->lop] |
+      | e[josh-created->lop] |
+      | e[josh-created->ripple] |
+      
+  Scenario: g_V_EXnullX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().E(null)
+      """
+    When iterated to list
+    Then the result should be empty
+
+  Scenario: g_V_EXlistXnullXX
+    Given the modern graph
+    And using the parameter xx1 defined as "l[null]"
+    And the traversal of
+      """
+      g.V().E(xx1)
+      """
+    When iterated to list
+    Then the result should be empty
+
+  Scenario: g_injectX1X_EX11_nullX
+    Given the modern graph
+    And using the parameter eid11 defined as "e[josh-created->lop].id"
+    And the traversal of
+      """
+      g.inject(1).E(eid11,null)
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | e[josh-created->lop] |
+
+ Scenario: g_injectX1X_coalesceXEX_hasLabelXtestsX_addEXtestsX_from_V_hasXnameX_XjoshXX_toXV_hasXnameX_XvadasXXX
+    Given the empty graph
+    And the graph initializer of
+      """
+      g.addV("person").property("name", "josh").
+        addV("person").property("name", "vadas")
+      """
+    And the traversal of
+      """
+      g.inject(1).coalesce(E().hasLabel("tests"), addE("tests").from(V().has("name","josh")).to(V().has("name","vadas")))
+      """
+    When iterated to list
+    Then the result should have a count of 1
+    And the graph should return 1 for count of "g.E().hasLabel(\"tests\")"
diff --git a/gremlin-tools/gremlin-benchmark/pom.xml b/gremlin-tools/gremlin-benchmark/pom.xml
index 6438584..287175a 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.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>gremlin-benchmark</artifactId>
@@ -31,6 +31,8 @@
         <!-- Skip benchmarks by default because they are time consuming. -->
         <skipBenchmarks>true</skipBenchmarks>
         <skipTests>${skipBenchmarks}</skipTests>
+        <!-- JDK17 fails javadoc generation here in benchmarks - not needed in any event -->
+        <maven.javadoc.skip>true</maven.javadoc.skip>
     </properties>
 
     <dependencies>
diff --git a/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/driver/GraphBinaryReaderWriterBenchmark.java b/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/driver/GraphBinaryReaderWriterBenchmark.java
index e247434..e091087 100644
--- a/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/driver/GraphBinaryReaderWriterBenchmark.java
+++ b/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/driver/GraphBinaryReaderWriterBenchmark.java
@@ -20,7 +20,7 @@
 
 import io.netty.buffer.UnpooledByteBufAllocator;
 import org.apache.tinkerpop.benchmark.util.AbstractBenchmarkBase;
-import org.apache.tinkerpop.gremlin.driver.ser.NettyBufferFactory;
+import org.apache.tinkerpop.gremlin.util.ser.NettyBufferFactory;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.structure.Graph;
diff --git a/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/driver/SerializationBenchmark.java b/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/driver/SerializationBenchmark.java
index 2d4ce84..5fa7f37 100644
--- a/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/driver/SerializationBenchmark.java
+++ b/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/driver/SerializationBenchmark.java
@@ -22,12 +22,13 @@
 import io.netty.buffer.Unpooled;
 import io.netty.buffer.UnpooledByteBufAllocator;
 import org.apache.tinkerpop.benchmark.util.AbstractBenchmarkBase;
-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.driver.ser.GraphBinaryMessageSerializerV1;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0;
-import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
+import org.apache.tinkerpop.gremlin.util.Tokens;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
+import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0;
+import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.structure.io.binary.DataType;
 import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceVertex;
diff --git a/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/jsr223/GremlinScriptCheckerBenchmark.java b/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/jsr223/GremlinScriptCheckerBenchmark.java
new file mode 100644
index 0000000..9b7ce46
--- /dev/null
+++ b/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/jsr223/GremlinScriptCheckerBenchmark.java
@@ -0,0 +1,49 @@
+/*
+ * 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.jsr223;
+
+import org.apache.tinkerpop.benchmark.util.AbstractBenchmarkBase;
+import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptChecker;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+
+import java.util.Optional;
+
+/**
+ * @author Valentyn Kahamlyk
+ */
+@State(Scope.Thread)
+public class GremlinScriptCheckerBenchmark extends AbstractBenchmarkBase {
+
+    @Benchmark
+    public Optional<String> testParseRequestId() {
+        return GremlinScriptChecker.parse("g.with('requestId', '4F53FB59-CFC9-4984-B477-452073A352FD').with(true).V().out('knows')").getRequestId();
+    }
+
+    @Benchmark
+    public Optional<String> testParseMaterializeProperties() {
+        return GremlinScriptChecker.parse("g.with('materializeProperties', 'all').with(true).V().out('knows')").getMaterializeProperties();
+    }
+
+    @Benchmark
+    public GremlinScriptChecker.Result testParseAll() {
+        return GremlinScriptChecker.parse("g.with('evaluationTimeout', 1000L).with('materializeProperties', 'all').with('requestId', '4F53FB59-CFC9-4984-B477-452073A352FD').with(true).V().out('knows')");
+    }
+}
diff --git a/gremlin-tools/gremlin-coverage/pom.xml b/gremlin-tools/gremlin-coverage/pom.xml
index 96b2f7b..c3faf00 100644
--- a/gremlin-tools/gremlin-coverage/pom.xml
+++ b/gremlin-tools/gremlin-coverage/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>gremlin-tools</artifactId>
         <groupId>org.apache.tinkerpop</groupId>
-        <version>3.6.5-SNAPSHOT</version>
+        <version>3.7.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 b446829..b0ce76a 100644
--- a/gremlin-tools/gremlin-io-test/pom.xml
+++ b/gremlin-tools/gremlin-io-test/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>gremlin-tools</artifactId>
         <groupId>org.apache.tinkerpop</groupId>
-        <version>3.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlin-io-test</artifactId>
     <name>Apache TinkerPop :: Gremlin IO Test</name>
@@ -41,23 +41,14 @@
             <artifactId>commons-io</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.codehaus.groovy</groupId>
+            <groupId>org.apache.groovy</groupId>
             <artifactId>groovy</artifactId>
             <version>${groovy.version}</version>
-            <classifier>indy</classifier>
         </dependency>
         <dependency>
-            <groupId>org.codehaus.groovy</groupId>
+            <groupId>org.apache.groovy</groupId>
             <artifactId>groovy-json</artifactId>
             <version>${groovy.version}</version>
-            <classifier>indy</classifier>
-            <exclusions>
-                <!-- exclude non-indy type -->
-                <exclusion>
-                    <groupId>org.codehaus.groovy</groupId>
-                    <artifactId>groovy</artifactId>
-                </exclusion>
-            </exclusions>
         </dependency>
         <dependency>
             <groupId>ch.qos.logback</groupId>
@@ -113,7 +104,7 @@
                         <artifactId>gmavenplus-plugin</artifactId>
                         <dependencies>
                             <dependency>
-                                <groupId>org.codehaus.groovy</groupId>
+                                <groupId>org.apache.groovy</groupId>
                                 <artifactId>groovy-all</artifactId>
                                 <version>${groovy.version}</version>
                                 <type>pom</type>
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 12ecadd..400edf2 100644
--- a/gremlin-tools/gremlin-io-test/scripts/generate-graphbinary-resources.groovy
+++ b/gremlin-tools/gremlin-io-test/scripts/generate-graphbinary-resources.groovy
@@ -19,7 +19,7 @@
 
 import io.netty.buffer.ByteBufAllocator
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter
-import org.apache.tinkerpop.gremlin.driver.ser.NettyBufferFactory
+import org.apache.tinkerpop.gremlin.util.ser.NettyBufferFactory
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.*
 import org.apache.tinkerpop.gremlin.structure.*
 import org.apache.tinkerpop.gremlin.structure.io.*
@@ -48,8 +48,8 @@
         buffer.readerIndex(0)
         buffer.readBytes(filestream, buffer.readableBytes())
     } catch (Exception ex) {
-        if (ex.message == "Serializer for type org.apache.tinkerpop.gremlin.driver.message.RequestMessage not found" ||
-                ex.message == "Serializer for type org.apache.tinkerpop.gremlin.driver.message.ResponseMessage not found" )
+        if (ex.message == "Serializer for type org.apache.tinkerpop.gremlin.util.message.RequestMessage not found" ||
+                ex.message == "Serializer for type org.apache.tinkerpop.gremlin.util.message.ResponseMessage not found" )
             fileToWriteTo.delete()
         else
             throw ex
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 537fb83..23404d3 100644
--- a/gremlin-tools/gremlin-io-test/scripts/generate-graphson-resources.groovy
+++ b/gremlin-tools/gremlin-io-test/scripts/generate-graphson-resources.groovy
@@ -18,7 +18,7 @@
  */
 
 import java.nio.file.Files
-import org.apache.tinkerpop.gremlin.driver.ser.*
+import org.apache.tinkerpop.gremlin.util.ser.*
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.*
 import org.apache.tinkerpop.gremlin.structure.*
 import org.apache.tinkerpop.gremlin.structure.io.graphson.*
@@ -138,7 +138,7 @@
         addRegistry(TinkerIoRegistryV2d0.instance()).
         typeInfo(TypeInfo.PARTIAL_TYPES).
         addCustomModule(GraphSONXModuleV2d0.build().create(false)).
-        addCustomModule(new org.apache.tinkerpop.gremlin.driver.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
+        addCustomModule(new org.apache.tinkerpop.gremlin.util.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
         version(GraphSONVersion.V2_0).create().createMapper()
 
 v2ExtendedDescription = """Note that the "extended" types require the addition of the separate `GraphSONXModuleV2d0` module as follows:
@@ -161,7 +161,7 @@
         addRegistry(TinkerIoRegistryV2d0.instance()).
         typeInfo(TypeInfo.NO_TYPES).
         addCustomModule(GraphSONXModuleV2d0.build().create(false)).
-        addCustomModule(new org.apache.tinkerpop.gremlin.driver.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
+        addCustomModule(new org.apache.tinkerpop.gremlin.util.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
         version(GraphSONVersion.V2_0).create().createMapper()
 
 file = new File("${projectBuildDir}/dev-docs/out-graphson-2d0-no-type.txt")
@@ -171,7 +171,7 @@
 mapper = GraphSONMapper.build().
         addRegistry(TinkerIoRegistryV2d0.instance()).
         addCustomModule(GraphSONXModuleV2d0.build().create(false)).
-        addCustomModule(new org.apache.tinkerpop.gremlin.driver.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
+        addCustomModule(new org.apache.tinkerpop.gremlin.util.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
         version(GraphSONVersion.V3_0).create().createMapper()
 
 v3ExtendedDescription = """Note that the "extended" types require the addition of the separate `GraphSONXModuleV3d0` module as follows:
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 4218883..1423aa3 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
@@ -20,8 +20,8 @@
 
 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.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.Operator;
 import org.apache.tinkerpop.gremlin.process.traversal.Order;
@@ -215,10 +215,10 @@
         addRequestMessageEntry(requestMessage, "Sessionless Eval Aliased", "The following `RequestMessage` is an example of a sessionless request for a script evaluation with an alias that binds the `TraversalSource` of \"g\" to \"social\".");
 
         ResponseMessage responseMessage = ResponseMessage.build(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).
-                code(org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode.AUTHENTICATE).create();
+                code(org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode.AUTHENTICATE).create();
         addResponseMessageEntry(responseMessage, "Authentication Challenge", "When authentication is enabled, an initial request to the server will result in an authentication challenge. The typical response message will appear as follows, but handling it could be different depending on the SASL implementation (e.g. multiple challenges maybe requested in some cases, but not in the default provided by Gremlin Server).");
         responseMessage = ResponseMessage.build(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).
-                code(org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode.SUCCESS).
+                code(org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode.SUCCESS).
                 result(Collections.singletonList(graph.vertices().next())).create();
         addResponseMessageEntry(responseMessage, "Standard Result", "The following `ResponseMessage` is a typical example of the typical successful response Gremlin Server will return when returning results from a script.");
         
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 19a8797..ae87c98 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
@@ -69,7 +69,9 @@
     V1_3_6_1("3.6.1", "1.0", "v1"),
     V1_3_6_2("3.6.2", "1.0", "v1"),
     V1_3_6_3("3.6.3", "1.0", "v1"),
-    V1_3_6_4("3.6.4", "1.0", "v1");
+    V1_3_6_4("3.6.4", "1.0", "v1"),
+
+    V1_3_7_0("3.7.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 170eeec..3d88142 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
@@ -209,7 +209,12 @@
     V1D0_3_6_4("3.6.4", "1.0", "v1d0"),
     V2D0_PARTIAL_3_6_4("3.6.4", "2.0", "v2d0-partial"),
     V2D0_NO_TYPE_3_6_4("3.6.4", "2.0", "v2d0-no-types"),
-    V3D0_PARTIAL_3_6_4("3.6.4", "3.0", "v3d0");
+    V3D0_PARTIAL_3_6_4("3.6.4", "3.0", "v3d0"),
+
+    V1D0_3_7_0("3.7.0", "1.0", "v1d0"),
+    V2D0_PARTIAL_3_7_0("3.7.0", "2.0", "v2d0-partial"),
+    V2D0_NO_TYPE_3_7_0("3.7.0", "2.0", "v2d0-no-types"),
+    V3D0_PARTIAL_3_7_0("3.7.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/AbstractTypedCompatibilityTest.java b/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/AbstractTypedCompatibilityTest.java
index 43cecd9..03dbd6d 100644
--- a/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/AbstractTypedCompatibilityTest.java
+++ b/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/AbstractTypedCompatibilityTest.java
@@ -18,8 +18,8 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io;
 
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.Operator;
 import org.apache.tinkerpop.gremlin.process.traversal.Order;
diff --git a/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/AbstractUntypedCompatibilityTest.java b/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/AbstractUntypedCompatibilityTest.java
index 3658c85..8dcbbb5 100644
--- a/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/AbstractUntypedCompatibilityTest.java
+++ b/gremlin-tools/gremlin-io-test/src/test/java/org/apache/tinkerpop/gremlin/structure/io/AbstractUntypedCompatibilityTest.java
@@ -18,9 +18,9 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io;
 
-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.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Property;
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 db427f6..71d39b5 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
@@ -20,7 +20,7 @@
 
 import io.netty.buffer.ByteBufAllocator;
 import org.apache.commons.io.output.ByteArrayOutputStream;
-import org.apache.tinkerpop.gremlin.driver.ser.NettyBufferFactory;
+import org.apache.tinkerpop.gremlin.util.ser.NettyBufferFactory;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter;
 import org.apache.tinkerpop.gremlin.structure.io.AbstractTypedCompatibilityTest;
@@ -72,6 +72,8 @@
                 {GraphBinaryCompatibility.V1_3_6_3, readerV1, writerV1 },
                 {GraphBinaryCompatibility.V1_3_6_4, readerV1, writerV1 },
 
+                {GraphBinaryCompatibility.V1_3_7_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 6044c45..bdc0732 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
@@ -38,13 +38,13 @@
             addRegistry(TinkerIoRegistryV2d0.instance()).
             typeInfo(TypeInfo.PARTIAL_TYPES).
             addCustomModule(GraphSONXModuleV2d0.build().create(false)).
-            addCustomModule(new org.apache.tinkerpop.gremlin.driver.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
+            addCustomModule(new org.apache.tinkerpop.gremlin.util.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
             version(GraphSONVersion.V2_0).create().createMapper();
 
     private static ObjectMapper mapperV3 = GraphSONMapper.build().
             addRegistry(TinkerIoRegistryV3d0.instance()).
             addCustomModule(GraphSONXModuleV3d0.build().create(false)).
-            addCustomModule(new org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0.GremlinServerModule()).
+            addCustomModule(new org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0.GremlinServerModule()).
             version(GraphSONVersion.V3_0).create().createMapper();
 
     @Parameterized.Parameters(name = "expect({0})")
@@ -138,6 +138,10 @@
                 {GraphSONCompatibility.V3D0_PARTIAL_3_6_3, mapperV3 },
                 {GraphSONCompatibility.V2D0_PARTIAL_3_6_4, mapperV2 },
                 {GraphSONCompatibility.V3D0_PARTIAL_3_6_4, mapperV3 },
+
+                {GraphSONCompatibility.V2D0_PARTIAL_3_7_0, mapperV2 },
+                {GraphSONCompatibility.V3D0_PARTIAL_3_7_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 20bb7a7..973d609 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
@@ -18,7 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.structure.io.graphson;
 
-import org.apache.tinkerpop.gremlin.driver.ser.AbstractGraphSONMessageSerializerV1d0;
+import org.apache.tinkerpop.gremlin.util.ser.AbstractGraphSONMessageSerializerV1d0;
 import org.apache.tinkerpop.gremlin.structure.io.AbstractUntypedCompatibilityTest;
 import org.apache.tinkerpop.gremlin.structure.io.Compatibility;
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV1d0;
@@ -44,7 +44,7 @@
                     addRegistry(TinkerIoRegistryV2d0.instance()).
                     typeInfo(TypeInfo.NO_TYPES).
                     addCustomModule(GraphSONXModuleV2d0.build().create(false)).
-                    addCustomModule(new org.apache.tinkerpop.gremlin.driver.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
+                    addCustomModule(new org.apache.tinkerpop.gremlin.util.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
                     version(GraphSONVersion.V2_0).create().createMapper();
 
     @Parameterized.Parameters(name = "expect({0})")
@@ -147,6 +147,9 @@
                 {GraphSONCompatibility.V1D0_3_6_4, mapperV1 },
                 {GraphSONCompatibility.V2D0_NO_TYPE_3_6_4, mapperV2 },
 
+                {GraphSONCompatibility.V1D0_3_7_0, mapperV1 },
+                {GraphSONCompatibility.V2D0_NO_TYPE_3_7_0, mapperV2 },
+
         });
     }
 
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_0/barrier-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/bigdecimal-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/biginteger-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/binding-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/bulkset-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/byte-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/bytebuffer-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/bytecode-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/cardinality-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/char-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/class-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/column-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/date-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/direction-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/double-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/duration-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/edge-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/float-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/inetaddress-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/instant-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/integer-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/lambda-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/list-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/localdate-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/localdatetime-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/localtime-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/long-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/map-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/metrics-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/monthday-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/offsetdatetime-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/offsettime-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/operator-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/order-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/p-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/pand-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/path-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/period-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/pick-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/pop-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/por-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/property-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/pwithin-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/pwithout-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/scope-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/set-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/short-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/t-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/textp-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/timestamp-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/tinkergraph-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/traversalmetrics-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/traverser-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/uuid-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/vertex-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/vertexproperty-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/year-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/yearmonth-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_7_0/zoneoffset-v1.gbin b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/_3_7_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_7_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_2_3/manual-graphson-generator.groovy b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_2_3/manual-graphson-generator.groovy
index 906aa31..b5d5a78 100644
--- a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_2_3/manual-graphson-generator.groovy
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_2_3/manual-graphson-generator.groovy
@@ -23,12 +23,12 @@
 
 import java.time.*
 import java.nio.file.*
-import org.apache.tinkerpop.gremlin.driver.ser.*
+import org.apache.tinkerpop.gremlin.util.ser.*
 import org.apache.tinkerpop.gremlin.process.traversal.*
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.*
 import org.apache.tinkerpop.gremlin.structure.*
 import org.apache.tinkerpop.gremlin.structure.io.graphson.*
-import org.apache.tinkerpop.gremlin.driver.message.*
+import org.apache.tinkerpop.gremlin.util.message.*
 import org.apache.tinkerpop.gremlin.process.traversal.step.*
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent.Pick
 import org.apache.commons.configuration.BaseConfiguration
@@ -110,10 +110,10 @@
     writer.write("ResponseMessage\n")
     writer.write("~~~~~~~~~~~~~~~\n\n")
     msg = ResponseMessage.build(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).
-            code(org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode.AUTHENTICATE).create()
+            code(org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode.AUTHENTICATE).create()
     writer.write(toJsonV1d0NoTypes(msg, "Authentication Challenge", mapper, "When authentication is enabled, an initial request to the server will result in an authentication challenge. The typical response message will appear as follows, but handling it could be different dependending on the SASL implementation (e.g. multiple challenges maybe requested in some cases, but not in the default provided by Gremlin Server)."))
     msg = ResponseMessage.build(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).
-            code(org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode.SUCCESS).
+            code(org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode.SUCCESS).
             result(Arrays.asList(graph.vertices().next())).create()
     writer.write(toJsonV1d0NoTypes(msg, "Standard Result", mapper, "The following `ResponseMessage` is a typical example of the typical successful response Gremlin Server will return when returning results from a script."))
 }
@@ -251,10 +251,10 @@
     writer.write("ResponseMessage\n")
     writer.write("~~~~~~~~~~~~~~~\n\n")
     msg = ResponseMessage.build(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).
-            code(org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode.AUTHENTICATE).create()
+            code(org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode.AUTHENTICATE).create()
     writer.write(toJsonFunction(msg, "Authentication Challenge", mapper, "When authentication is enabled, an initial request to the server will result in an authentication challenge. The typical response message will appear as follows, but handling it could be different dependending on the SASL implementation (e.g. multiple challenges maybe requested in some cases, but not in the default provided by Gremlin Server)."))
     msg = ResponseMessage.build(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).
-            code(org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode.SUCCESS).
+            code(org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode.SUCCESS).
             result(Arrays.asList(graph.vertices().next())).create()
     writer.write(toJsonFunction(msg, "Standard Result", mapper, "The following `ResponseMessage` is a typical example of the typical successful response Gremlin Server will return when returning results from a script."))
 
@@ -296,7 +296,7 @@
         addRegistry(TinkerIoRegistryV2d0.instance()).
         typeInfo(TypeInfo.PARTIAL_TYPES).
         addCustomModule(GraphSONXModuleV2d0.build().create(false)).
-        addCustomModule(new org.apache.tinkerpop.gremlin.driver.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
+        addCustomModule(new org.apache.tinkerpop.gremlin.util.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
         version(GraphSONVersion.V2_0).create().createMapper()
 
 file = new File("dev-docs/out-graphson-2d0-partial.txt")
@@ -306,7 +306,7 @@
         addRegistry(TinkerIoRegistryV2d0.instance()).
         typeInfo(TypeInfo.NO_TYPES).
         addCustomModule(GraphSONXModuleV2d0.build().create(false)).
-        addCustomModule(new org.apache.tinkerpop.gremlin.driver.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
+        addCustomModule(new org.apache.tinkerpop.gremlin.util.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
         version(GraphSONVersion.V2_0).create().createMapper()
 
 file = new File("dev-docs/out-graphson-2d0-no-type.txt")
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_2_4/manual-graphson-generator.groovy b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_2_4/manual-graphson-generator.groovy
index 4624bda..bdb327b 100644
--- a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_2_4/manual-graphson-generator.groovy
+++ b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_2_4/manual-graphson-generator.groovy
@@ -23,12 +23,12 @@
 
 import java.time.*
 import java.nio.file.*
-import org.apache.tinkerpop.gremlin.driver.ser.*
+import org.apache.tinkerpop.gremlin.util.ser.*
 import org.apache.tinkerpop.gremlin.process.traversal.*
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.*
 import org.apache.tinkerpop.gremlin.structure.*
 import org.apache.tinkerpop.gremlin.structure.io.graphson.*
-import org.apache.tinkerpop.gremlin.driver.message.*
+import org.apache.tinkerpop.gremlin.util.message.*
 import org.apache.tinkerpop.gremlin.process.traversal.step.*
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent.Pick
 import org.apache.commons.configuration.BaseConfiguration
@@ -110,10 +110,10 @@
     writer.write("ResponseMessage\n")
     writer.write("~~~~~~~~~~~~~~~\n\n")
     msg = ResponseMessage.build(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).
-            code(org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode.AUTHENTICATE).create()
+            code(org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode.AUTHENTICATE).create()
     writer.write(toJsonV1d0NoTypes(msg, "Authentication Challenge", mapper, "When authentication is enabled, an initial request to the server will result in an authentication challenge. The typical response message will appear as follows, but handling it could be different dependending on the SASL implementation (e.g. multiple challenges maybe requested in some cases, but not in the default provided by Gremlin Server)."))
     msg = ResponseMessage.build(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).
-            code(org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode.SUCCESS).
+            code(org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode.SUCCESS).
             result(Arrays.asList(graph.vertices().next())).create()
     writer.write(toJsonV1d0NoTypes(msg, "Standard Result", mapper, "The following `ResponseMessage` is a typical example of the typical successful response Gremlin Server will return when returning results from a script."))
 }
@@ -251,10 +251,10 @@
     writer.write("ResponseMessage\n")
     writer.write("~~~~~~~~~~~~~~~\n\n")
     msg = ResponseMessage.build(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).
-            code(org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode.AUTHENTICATE).create()
+            code(org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode.AUTHENTICATE).create()
     writer.write(toJsonFunction(msg, "Authentication Challenge", mapper, "When authentication is enabled, an initial request to the server will result in an authentication challenge. The typical response message will appear as follows, but handling it could be different dependending on the SASL implementation (e.g. multiple challenges maybe requested in some cases, but not in the default provided by Gremlin Server)."))
     msg = ResponseMessage.build(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).
-            code(org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode.SUCCESS).
+            code(org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode.SUCCESS).
             result(Arrays.asList(graph.vertices().next())).create()
     writer.write(toJsonFunction(msg, "Standard Result", mapper, "The following `ResponseMessage` is a typical example of the typical successful response Gremlin Server will return when returning results from a script."))
 
@@ -296,7 +296,7 @@
         addRegistry(TinkerIoRegistryV2d0.instance()).
         typeInfo(TypeInfo.PARTIAL_TYPES).
         addCustomModule(GraphSONXModuleV2d0.build().create(false)).
-        addCustomModule(new org.apache.tinkerpop.gremlin.driver.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
+        addCustomModule(new org.apache.tinkerpop.gremlin.util.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
         version(GraphSONVersion.V2_0).create().createMapper()
 
 file = new File("dev-docs/out-graphson-2d0-partial.txt")
@@ -306,7 +306,7 @@
         addRegistry(TinkerIoRegistryV2d0.instance()).
         typeInfo(TypeInfo.NO_TYPES).
         addCustomModule(GraphSONXModuleV2d0.build().create(false)).
-        addCustomModule(new org.apache.tinkerpop.gremlin.driver.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
+        addCustomModule(new org.apache.tinkerpop.gremlin.util.ser.AbstractGraphSONMessageSerializerV2d0.GremlinServerModule()).
         version(GraphSONVersion.V2_0).create().createMapper()
 
 file = new File("dev-docs/out-graphson-2d0-no-type.txt")
diff --git a/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_0/authenticationchallenge-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/authenticationchallenge-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/authenticationchallenge-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/authenticationchallenge-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/authenticationresponse-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/authenticationresponse-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/authenticationresponse-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/authenticationresponse-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/barrier-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/barrier-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/bigdecimal-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/bigdecimal-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/biginteger-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/biginteger-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/binding-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/binding-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/bulkset-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/bulkset-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/byte-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/byte-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/bytebuffer-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/bytebuffer-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/bytecode-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/bytecode-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/cardinality-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/cardinality-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/char-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/char-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/class-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/class-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/column-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/column-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/date-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/date-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/date-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/direction-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/direction-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/double-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/double-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/double-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/duration-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/duration-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/edge-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/edge-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/edge-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/edge-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/float-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/float-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/inetaddress-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/inetaddress-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/instant-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/instant-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/integer-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/integer-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/integer-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/lambda-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/lambda-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/list-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/localdate-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/localdate-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/localdatetime-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/localdatetime-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/localtime-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/localtime-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/long-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/long-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/map-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/metrics-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/metrics-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/monthday-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/monthday-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/offsetdatetime-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/offsetdatetime-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/offsettime-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/offsettime-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/operator-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/operator-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/order-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/order-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/p-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/p-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/pand-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/pand-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/path-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/path-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/path-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/path-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/period-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/period-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/pick-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/pick-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/pop-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/pop-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/por-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/por-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/property-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/property-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/property-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/property-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/pwithin-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/pwithin-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/pwithout-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/pwithout-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/scope-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/scope-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessionclose-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessionclose-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessionclose-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessionclose-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessioneval-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessioneval-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessioneval-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessioneval-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessionevalaliased-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessionevalaliased-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessionevalaliased-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessionevalaliased-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessionlesseval-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessionlesseval-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessionlesseval-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessionlesseval-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessionlessevalaliased-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessionlessevalaliased-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessionlessevalaliased-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/sessionlessevalaliased-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/set-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/short-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/short-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/standardresult-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/standardresult-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/standardresult-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/t-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/t-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/textp-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/textp-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/timestamp-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/timestamp-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/tinkergraph-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/tinkergraph-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/tinkergraph-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/tinkergraph-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/traversalmetrics-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/traversalmetrics-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/traverser-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/traverser-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/uuid-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/uuid-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/uuid-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/vertex-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/vertex-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/vertex-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/vertex-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/vertexproperty-v1d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/vertexproperty-v2d0-no-types.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/vertexproperty-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/vertexproperty-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/year-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/year-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/yearmonth-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/yearmonth-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/zoneddatetime-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/zoneddatetime-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/zoneoffset-v2d0-partial.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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_7_0/zoneoffset-v3d0.json b/gremlin-tools/gremlin-io-test/src/test/resources/org/apache/tinkerpop/gremlin/structure/io/graphson/_3_7_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_7_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-socket-server/Dockerfile b/gremlin-tools/gremlin-socket-server/Dockerfile
new file mode 100644
index 0000000..9eef686
--- /dev/null
+++ b/gremlin-tools/gremlin-socket-server/Dockerfile
@@ -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.
+
+FROM alpine
+
+LABEL maintainer="dev@tinkerpop.apache.org"
+
+ARG SOCKET_SERVER_DIR
+ARG SOCKET_SERVER_VERSION
+
+RUN apk add --no-cache --update \
+    bash \
+    openjdk11-jdk
+
+COPY ${SOCKET_SERVER_DIR}/gremlin-socket-server-${SOCKET_SERVER_VERSION}.jar /opt/gremlin-socket-server/gremlin-socket-server.jar
+COPY ${SOCKET_SERVER_DIR}/libs/ /opt/gremlin-socket-server/libs/
+COPY ${SOCKET_SERVER_DIR}/../conf/ opt/gremlin-socket-server/conf/
+
+WORKDIR /opt/gremlin-socket-server
+
+EXPOSE 45943
+
+ENTRYPOINT ["java","-jar","gremlin-socket-server.jar"]
diff --git a/gremlin-tools/gremlin-socket-server/conf/test-ws-gremlin.yaml b/gremlin-tools/gremlin-socket-server/conf/test-ws-gremlin.yaml
new file mode 100644
index 0000000..a358d4c
--- /dev/null
+++ b/gremlin-tools/gremlin-socket-server/conf/test-ws-gremlin.yaml
@@ -0,0 +1,56 @@
+# 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 is to be used to configure an instance of Gremlin-Socket-Server as
+# well as any driver trying to run tests against it.
+# Gremlin-Socket-Server listens for requests with the specific request ids below
+# and triggers response behavior accordingly. Driver's should use the request id
+# corresponding with the desired behavior whenever sending a  request to
+#  gremlin-socket-server.
+
+# Port exposed by gremlin-socket-server
+PORT: 45943
+
+# Configures which serializer will be used. Ex: GraphBinaryV1 or GraphSONV2
+SERIALIZER: GraphBinaryV1
+
+# If a request with this ID comes to the server, the server responds back with a single
+# vertex picked from Modern graph.
+SINGLE_VERTEX_REQUEST_ID: 6457272a-4018-4538-b9ae-08dd5ddc0aa1
+
+# If a request with this ID comes to the server, the server responds back with a single
+# vertex picked from Modern graph. After a 2 second delay, server sends a Close WebSocket
+# frame on the same connection.
+SINGLE_VERTEX_DELAYED_CLOSE_CONNECTION_REQUEST_ID: 3cb39c94-9454-4398-8430-03485d08bdae
+
+# Server waits for 1 second, then responds with a 500 error status code
+FAILED_AFTER_DELAY_REQUEST_ID: edf79c8b-1d32-4102-a5d2-a5feeca40864
+
+# Server waits for 1 second then responds with a close web socket frame
+CLOSE_CONNECTION_REQUEST_ID: 0150143b-00f9-48a7-a268-28142d902e18
+
+# Same as CLOSE_CONNECTION_REQUEST_ID
+CLOSE_CONNECTION_REQUEST_ID_2: 3c4cf18a-c7f2-4dad-b9bf-5c701eb33000
+
+# If a request with this ID comes to the server, the server responds with the user agent (if any)
+# that was captured during the web socket handshake.
+USER_AGENT_REQUEST_ID: 20ad7bfb-4abf-d7f4-f9d3-9f1d55bee4ad
+
+# If a request with this ID comes to the server, the server responds with a string containing all overridden
+# per request settings from the request message. String will be of the form
+# "requestId=19436d9e-f8fc-4b67-8a76-deec60918424 evaluationTimeout=1234, batchSize=12, userAgent=testUserAgent"
+PER_REQUEST_SETTINGS_REQUEST_ID: 19436d9e-f8fc-4b67-8a76-deec60918424
diff --git a/gremlin-tools/gremlin-socket-server/pom.xml b/gremlin-tools/gremlin-socket-server/pom.xml
new file mode 100644
index 0000000..da66a3b
--- /dev/null
+++ b/gremlin-tools/gremlin-socket-server/pom.xml
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>gremlin-tools</artifactId>
+        <groupId>org.apache.tinkerpop</groupId>
+        <version>3.7.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>gremlin-socket-server</artifactId>
+    <name>Apache TinkerPop :: Gremlin Socket Server</name>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.tinkerpop</groupId>
+            <artifactId>gremlin-util</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tinkerpop</groupId>
+            <artifactId>tinkergraph-gremlin</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-all</artifactId>
+            <version>${netty.version}</version>
+        </dependency>
+        <!-- LOGGING -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>jcl-over-slf4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.groovy</groupId>
+            <artifactId>groovy</artifactId>
+            <version>${groovy.version}</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.groovy</groupId>
+            <artifactId>groovy-json</artifactId>
+            <version>${groovy.version}</version>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+
+    <properties>
+        <!--
+        provides a way to convert maven.exec.skip value to skipImageBuild for use in skipping image building for testing
+        under incompatible platforms
+        -->
+        <maven.exec.skip>false</maven.exec.skip> <!-- default -->
+        <skipImageBuild>${maven.exec.skip}</skipImageBuild>
+    </properties>
+
+    <build>
+        <directory>${basedir}/target</directory>
+        <finalName>${project.artifactId}-${project.version}</finalName>
+        <testSourceDirectory>${basedir}/src/test/java</testSourceDirectory>
+        <resources>
+            <resource>
+                <directory>${basedir}/src/main/resources
+                </directory>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy-dependencies</id>
+                        <phase>prepare-package</phase>
+                        <goals>
+                            <goal>copy-dependencies</goal>
+                        </goals>
+                        <configuration>
+                            <outputDirectory>
+                                ${project.build.directory}/libs
+                            </outputDirectory>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>3.2.0</version>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <mainClass>org.apache.tinkerpop.gremlin.socket.server.SocketServerRunner</mainClass>
+                            <addClasspath>true</addClasspath>
+                            <classpathPrefix>libs/</classpathPrefix>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-failsafe-plugin</artifactId>
+            </plugin>
+            <!--
+            gremlin socket server image will be generated on each build as language variants will need the latest to do
+            their work.
+            -->
+            <plugin>
+                <artifactId>exec-maven-plugin</artifactId>
+                <groupId>org.codehaus.mojo</groupId>
+                <version>1.2.1</version>
+                <executions>
+                    <execution>
+                        <id>build-image</id>
+                        <phase>install</phase>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <configuration>
+                            <skip>${skipImageBuild}</skip>
+                            <executable>docker</executable>
+                            <arguments>
+                                <argument>build</argument>
+                                <argument>-f</argument>
+                                <argument>./Dockerfile</argument>
+                                <argument>--build-arg</argument>
+                                <argument>SOCKET_SERVER_DIR=target/</argument>
+                                <argument>--build-arg</argument>
+                                <argument>SOCKET_SERVER_VERSION=${project.version}</argument>
+                                <argument>-t</argument>
+                                <argument>tinkerpop/gremlin-socket-server:${project.version}</argument>
+                                <argument>.</argument>
+                            </arguments>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>remove-dangling-images</id>
+                        <phase>install</phase>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <configuration>
+                            <skip>${skipImageBuild}</skip>
+                            <executable>docker</executable>
+                            <arguments>
+                                <argument>image</argument>
+                                <argument>prune</argument>
+                                <argument>--filter</argument>
+                                <argument>label=maintainer=dev@tinkerpop.apache.org</argument>
+                                <argument>-f</argument>
+                            </arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/SimpleSocketServer.java b/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/SimpleSocketServer.java
similarity index 82%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/SimpleSocketServer.java
rename to gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/SimpleSocketServer.java
index dc9c513..e728b03 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/SimpleSocketServer.java
+++ b/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/SimpleSocketServer.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver;
+package org.apache.tinkerpop.gremlin.socket.server;
 
 import io.netty.bootstrap.ServerBootstrap;
 import io.netty.channel.Channel;
@@ -29,13 +29,18 @@
 import io.netty.handler.logging.LoggingHandler;
 
 /**
- * Simple Netty Server
+ * A Simple Netty Server intended to be used as a base for gremlin test servers.
+ * Server behavior is defined by the {@link ChannelInitializer} passed in the start method.
  */
 public class SimpleSocketServer {
-    public static final int PORT = 45940;
+    private final SocketServerSettings settings;
     private EventLoopGroup bossGroup;
     private EventLoopGroup workerGroup;
 
+    public SimpleSocketServer(final SocketServerSettings settings) {
+        this.settings = settings;
+    }
+
     public Channel start(final ChannelInitializer<SocketChannel> channelInitializer) throws InterruptedException {
         bossGroup = new NioEventLoopGroup(1);
         workerGroup = new NioEventLoopGroup();
@@ -44,7 +49,7 @@
                 .channel(NioServerSocketChannel.class)
                 .handler(new LoggingHandler(LogLevel.INFO))
                 .childHandler(channelInitializer);
-        return b.bind(PORT).sync().channel();
+        return b.bind(settings.PORT).sync().channel();
     }
 
     public void stop() {
diff --git a/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/SocketServerRunner.java b/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/SocketServerRunner.java
new file mode 100644
index 0000000..9886569
--- /dev/null
+++ b/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/SocketServerRunner.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.socket.server;
+
+import io.netty.channel.Channel;
+
+import java.io.IOException;
+import java.nio.file.FileSystems;
+
+/**
+ * A simple main class to create and run a SimpleSocketServer
+ */
+public class SocketServerRunner {
+
+    public static void main(final String[] args) throws InterruptedException, IOException {
+        final SocketServerSettings settings = SocketServerSettings.read(FileSystems.getDefault().getPath("conf", "test-ws-gremlin.yaml"));
+        final SimpleSocketServer server = new SimpleSocketServer(settings);
+        final Channel channel = server.start(new TestWSGremlinInitializer(settings));
+        while(channel.isOpen()) {
+            Thread.sleep(1000);
+        }
+    }
+
+}
diff --git a/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/SocketServerSettings.java b/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/SocketServerSettings.java
new file mode 100644
index 0000000..08a418d
--- /dev/null
+++ b/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/SocketServerSettings.java
@@ -0,0 +1,93 @@
+/*
+ * 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.socket.server;
+
+import org.yaml.snakeyaml.LoaderOptions;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.Constructor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.UUID;
+
+/**
+ * Encapsulates all constants that are needed by SimpleSocketServer. UUID request id constants are used
+ * to coordinate custom response behavior between a test client and the server.
+ */
+public class SocketServerSettings {
+    public int PORT = 0;
+
+    /**
+     * Configures which serializer will be used. Ex: "GraphBinaryV1" or "GraphSONV2"
+     */
+    public String SERIALIZER = "GraphBinaryV1";
+    /**
+     * If a request with this ID comes to the server, the server responds back with a single vertex picked from Modern
+     * graph.
+     */
+    public UUID SINGLE_VERTEX_REQUEST_ID = null;
+
+    /**
+     * If a request with this ID comes to the server, the server responds back with a single vertex picked from Modern
+     * graph. After a 2 second delay, server sends a Close WebSocket frame on the same connection.
+     */
+    public UUID SINGLE_VERTEX_DELAYED_CLOSE_CONNECTION_REQUEST_ID = null;
+
+    /**
+     * Server waits for 1 second, then responds with a 500 error status code
+     */
+    public UUID FAILED_AFTER_DELAY_REQUEST_ID = null;
+
+    /**
+     * Server waits for 1 second then responds with a close web socket frame
+     */
+    public UUID CLOSE_CONNECTION_REQUEST_ID = null;
+
+    /**
+     * Same as CLOSE_CONNECTION_REQUEST_ID
+     */
+    public UUID CLOSE_CONNECTION_REQUEST_ID_2 = null;
+
+    /**
+     * If a request with this ID comes to the server, the server responds with the user agent (if any) that was captured
+     * during the web socket handshake.
+     */
+    public UUID USER_AGENT_REQUEST_ID = null;
+
+    /**
+     * If a request with this ID comes to the server, the server responds with a string containing all overridden
+     * per request settings from the request message. String will be of the form
+     * "requestId=19436d9e-f8fc-4b67-8a76-deec60918424 evaluationTimeout=1234, batchSize=12, userAgent=testUserAgent"
+     */
+    public UUID PER_REQUEST_SETTINGS_REQUEST_ID = null;
+
+    public static SocketServerSettings read(final Path confFilePath) throws IOException {
+        return read(Files.newInputStream(confFilePath));
+    }
+
+    public static SocketServerSettings read(final InputStream confInputStream) {
+        Objects.requireNonNull(confInputStream);
+        final LoaderOptions options = new LoaderOptions();
+        final Yaml yaml = new Yaml(new Constructor(SocketServerSettings.class, options));
+        return yaml.load(confInputStream);
+    }
+}
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/TestChannelizers.java b/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/TestChannelizers.java
similarity index 93%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/TestChannelizers.java
rename to gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/TestChannelizers.java
index 8e05ff3..8639f7a 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/TestChannelizers.java
+++ b/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/TestChannelizers.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver;
+package org.apache.tinkerpop.gremlin.socket.server;
 
 import io.netty.channel.ChannelInitializer;
 import io.netty.channel.ChannelPipeline;
@@ -82,6 +82,9 @@
      */
     public static class TestConnectionThrottlingInitializer extends TestHttpServerInitializer {
         int connectionCount = 0;
+        private SocketServerSettings settings;
+
+        public TestConnectionThrottlingInitializer(SocketServerSettings settings) { this.settings = settings; }
 
         @Override
         public void initChannel(SocketChannel ch) {
@@ -91,7 +94,7 @@
             if (connectionCount < 1) {
                 pipeline.addLast(new WebSocketServerCompressionHandler());
                 pipeline.addLast(new WebSocketServerProtocolHandler(WEBSOCKET_PATH, null, true));
-                pipeline.addLast(new TestWSGremlinInitializer.ClientTestConfigurableHandler());
+                pipeline.addLast(new TestWSGremlinInitializer.ClientTestConfigurableHandler(settings));
             } else {
                 pipeline.addLast(new TestHandlers.NoOpWebSocketServerHandler(WEBSOCKET_PATH));
             }
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/TestHandlers.java b/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/TestHandlers.java
similarity index 96%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/TestHandlers.java
rename to gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/TestHandlers.java
index e373b02..c2f0af0 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/TestHandlers.java
+++ b/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/TestHandlers.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver;
+package org.apache.tinkerpop.gremlin.socket.server;
 
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
diff --git a/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/TestWSGremlinInitializer.java b/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/TestWSGremlinInitializer.java
new file mode 100644
index 0000000..f8f48e2
--- /dev/null
+++ b/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/TestWSGremlinInitializer.java
@@ -0,0 +1,195 @@
+/*
+ * 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.socket.server;
+
+import io.netty.buffer.ByteBufAllocator;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import io.netty.handler.codec.http.HttpHeaders;
+import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
+import org.apache.tinkerpop.gremlin.util.ser.AbstractMessageSerializer;
+import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
+import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV2d0;
+import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelPipeline;
+import io.netty.handler.codec.MessageToMessageDecoder;
+import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
+import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+
+/**
+ * Initializer which partially mimics the Gremlin Server. This initializer injects a handler in the
+ * server pipeline that can be modified to send the desired response for a test case.
+ * This handler identifies incoming requests with ids matching those in {@link SocketServerSettings}
+ * and delivers the response which corresponds to the request id.
+ */
+public class TestWSGremlinInitializer extends TestChannelizers.TestWebSocketServerInitializer {
+    private static final Logger logger = LoggerFactory.getLogger(TestWSGremlinInitializer.class);
+    private static final String USER_AGENT_HEADER = "User-Agent";
+
+    private final SocketServerSettings settings;
+
+    /**
+     * Gremlin serializer used for serializing/deserializing the request/response. This should be same as client.
+     */
+    private static AbstractMessageSerializer SERIALIZER;
+    private final static ByteBufAllocator allocator = UnpooledByteBufAllocator.DEFAULT;
+
+    public TestWSGremlinInitializer(final SocketServerSettings settings) {
+        this.settings = settings;
+        switch(settings.SERIALIZER) {
+            case "GraphSONV2":
+                SERIALIZER = new GraphSONMessageSerializerV2d0();
+                break;
+            case "GraphSONV3":
+                SERIALIZER = new GraphSONMessageSerializerV3d0();
+                break;
+            case "GraphBinaryV1":
+                SERIALIZER = new GraphBinaryMessageSerializerV1();
+                break;
+            default:
+                logger.warn("Could not recognize serializer [%s], defaulting to GraphBinaryV1", settings.SERIALIZER);
+                SERIALIZER = new GraphBinaryMessageSerializerV1();
+                break;
+        }
+    }
+
+    @Override
+    public void postInit(ChannelPipeline pipeline) {
+        pipeline.addLast(new ClientTestConfigurableHandler(settings));
+    }
+
+    /**
+     * Handler introduced in the server pipeline to configure expected response for test cases.
+     */
+    static class ClientTestConfigurableHandler extends MessageToMessageDecoder<BinaryWebSocketFrame> {
+        private SocketServerSettings settings;
+        private String userAgent = "";
+
+        public ClientTestConfigurableHandler(SocketServerSettings settings) { this.settings = settings; }
+
+        @Override
+        protected void decode(final ChannelHandlerContext ctx, final BinaryWebSocketFrame frame, final List<Object> objects)
+                throws Exception {
+            final ByteBuf messageBytes = frame.content();
+            final byte len = messageBytes.readByte();
+            if (len <= 0) {
+                objects.add(RequestMessage.INVALID);
+                return;
+            }
+
+            final ByteBuf contentTypeBytes = ctx.alloc().buffer(len);
+            try {
+                messageBytes.readBytes(contentTypeBytes);
+            } finally {
+                contentTypeBytes.release();
+            }
+            final RequestMessage msg = SERIALIZER.deserializeRequest(messageBytes.discardReadBytes());
+            if (msg.getRequestId().equals(settings.SINGLE_VERTEX_DELAYED_CLOSE_CONNECTION_REQUEST_ID)) {
+                logger.info("sending vertex result frame");
+                ctx.channel().writeAndFlush(new BinaryWebSocketFrame(returnSingleVertexResponse(
+                        settings.SINGLE_VERTEX_DELAYED_CLOSE_CONNECTION_REQUEST_ID)));
+                logger.info("waiting for 2 sec");
+                Thread.sleep(2000);
+                logger.info("sending close frame");
+                ctx.channel().writeAndFlush(new CloseWebSocketFrame());
+            } else if (msg.getRequestId().equals(settings.SINGLE_VERTEX_REQUEST_ID)) {
+                logger.info("sending vertex result frame");
+                ctx.channel().writeAndFlush(new BinaryWebSocketFrame(returnSingleVertexResponse(settings.SINGLE_VERTEX_REQUEST_ID)));
+            } else if (msg.getRequestId().equals(settings.FAILED_AFTER_DELAY_REQUEST_ID)) {
+                logger.info("waiting for 1 sec");
+                Thread.sleep(1000);
+                final ResponseMessage responseMessage = ResponseMessage.build(msg)
+                        .code(ResponseStatusCode.SERVER_ERROR)
+                        .statusAttributeException(new RuntimeException()).create();
+                ctx.channel().writeAndFlush(new BinaryWebSocketFrame(SERIALIZER.serializeResponseAsBinary(responseMessage, allocator)));
+            } else if (msg.getRequestId().equals(settings.CLOSE_CONNECTION_REQUEST_ID) || msg.getRequestId().equals(settings.CLOSE_CONNECTION_REQUEST_ID_2)) {
+                Thread.sleep(1000);
+                ctx.channel().writeAndFlush(new CloseWebSocketFrame());
+            } else if (msg.getRequestId().equals(settings.USER_AGENT_REQUEST_ID)) {
+                ctx.channel().writeAndFlush(new BinaryWebSocketFrame(returnSimpleBinaryResponse(settings.USER_AGENT_REQUEST_ID, userAgent)));
+            } else if (msg.getRequestId().equals(settings.PER_REQUEST_SETTINGS_REQUEST_ID)) {
+                String response = String.format("requestId=%s evaluationTimeout=%d, batchSize=%d, userAgent=%s",
+                        msg.getRequestId(), msg.getArgs().get("evaluationTimeout"),
+                        msg.getArgs().get("batchSize"), msg.getArgs().get("userAgent"));
+                ctx.channel().writeAndFlush(new BinaryWebSocketFrame(returnSimpleBinaryResponse(settings.PER_REQUEST_SETTINGS_REQUEST_ID, response)));
+            } else {
+                try {
+                    Thread.sleep(Long.parseLong((String) msg.getArgs().get("gremlin")));
+                    ctx.channel().writeAndFlush(new BinaryWebSocketFrame(returnSingleVertexResponse(msg.getRequestId())));
+                } catch (NumberFormatException nfe) {
+                    // Ignore. Only return a vertex if the query was a long value.
+                    logger.warn("Request unknown request with RequestId: %s", msg.getRequestId());
+                }
+            }
+        }
+
+        private ByteBuf returnSingleVertexResponse(final UUID requestID) throws SerializationException {
+            final TinkerGraph graph = TinkerFactory.createClassic();
+            final GraphTraversalSource g = graph.traversal();
+            final List<Vertex> t = new ArrayList<>(1);
+            t.add(g.V().limit(1).next());
+
+            return SERIALIZER.serializeResponseAsBinary(ResponseMessage.build(requestID).result(t).create(), allocator);
+        }
+
+        /**
+         * Packages a string message into a ResponseMessage and serializes it into a ByteBuf
+         * @throws SerializationException
+         */
+        private ByteBuf returnSimpleBinaryResponse(final UUID requestID, String message) throws SerializationException {
+            //Need to package message in a list of size 1 as some GLV's serializers require all messages to be in a list
+            final List<String> messageList = new ArrayList<>(1);
+            messageList.add(message);
+            return SERIALIZER.serializeResponseAsBinary(ResponseMessage.build(requestID).result(messageList).create(), allocator);
+        }
+
+        /**
+         * Captures and stores User-Agent if included in header
+         */
+        @Override
+        public void userEventTriggered(final ChannelHandlerContext ctx, final Object evt) {
+            if(evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
+                WebSocketServerProtocolHandler.HandshakeComplete handshake = (WebSocketServerProtocolHandler.HandshakeComplete) evt;
+                HttpHeaders requestHeaders = handshake.requestHeaders();
+                if(requestHeaders.contains(USER_AGENT_HEADER)) {
+                    userAgent = requestHeaders.get(USER_AGENT_HEADER);
+                }
+                else {
+                    ctx.fireUserEventTriggered(evt);
+                }
+            }
+        }
+    }
+}
diff --git a/gremlin-tools/pom.xml b/gremlin-tools/pom.xml
index 51d82c6..e5ac3d4 100644
--- a/gremlin-tools/pom.xml
+++ b/gremlin-tools/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>tinkerpop</artifactId>
         <groupId>org.apache.tinkerpop</groupId>
-        <version>3.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>gremlin-tools</artifactId>
@@ -31,6 +31,7 @@
         <module>gremlin-benchmark</module>
         <module>gremlin-coverage</module>
         <module>gremlin-io-test</module>
+        <module>gremlin-socket-server</module>
     </modules>
 
     <build>
diff --git a/gremlin-util/pom.xml b/gremlin-util/pom.xml
new file mode 100644
index 0000000..ec8bffe
--- /dev/null
+++ b/gremlin-util/pom.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>tinkerpop</artifactId>
+        <groupId>org.apache.tinkerpop</groupId>
+        <version>3.7.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>gremlin-util</artifactId>
+    <name>Apache TinkerPop :: Gremlin Util</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.tinkerpop</groupId>
+            <artifactId>gremlin-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-all</artifactId>
+            <version>${netty.version}</version>
+        </dependency>
+        <!-- LOGGING -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>jcl-over-slf4j</artifactId>
+        </dependency>
+        <!-- TEST -->
+        <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>tinkergraph-gremlin</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-failsafe-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/MessageSerializer.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/MessageSerializer.java
similarity index 91%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/MessageSerializer.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/MessageSerializer.java
index 8b21ec4..91857b1 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/MessageSerializer.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/MessageSerializer.java
@@ -16,12 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver;
+package org.apache.tinkerpop.gremlin.util;
 
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0;
-import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV1d0;
+import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/Tokens.java
similarity index 86%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/Tokens.java
index ba9b6fd..6391852 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/Tokens.java
@@ -16,9 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver;
+package org.apache.tinkerpop.gremlin.util;
 
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
 import org.apache.tinkerpop.gremlin.process.traversal.Failure;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.structure.Graph;
@@ -79,6 +79,22 @@
     public static final String ARGS_HOST = "host";
     public static final String ARGS_SESSION = "session";
     public static final String ARGS_MANAGE_TRANSACTION = "manageTransaction";
+    /**
+     * The name of the argument that allows to control the serialization of properties on the server.
+     */
+    public static final String ARGS_MATERIALIZE_PROPERTIES = "materializeProperties";
+
+    /**
+     * The name of the value denoting that all properties of Element should be returned.
+     * Should be used with {@code ARGS_MATERIALIZE_PROPERTIES}
+     */
+
+    public static final String MATERIALIZE_PROPERTIES_ALL = "all";
+    /**
+     * The name of the value denoting that only `ID` and `Label` of Element should be returned.
+     * Should be used with {@code ARGS_MATERIALIZE_PROPERTIES}
+     */
+    public static final String MATERIALIZE_PROPERTIES_TOKENS = "tokens";
 
     /**
      * Argument name that is intended to be used with a session which when its value is {@code true} makes it so
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/RequestMessage.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/RequestMessage.java
similarity index 97%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/RequestMessage.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/RequestMessage.java
index aeebf35..75697c1 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/RequestMessage.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/RequestMessage.java
@@ -16,9 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.message;
+package org.apache.tinkerpop.gremlin.util.message;
 
-import org.apache.tinkerpop.gremlin.driver.Tokens;
+import org.apache.tinkerpop.gremlin.util.Tokens;
 import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
 
 import java.util.HashMap;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseMessage.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/ResponseMessage.java
similarity index 97%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseMessage.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/ResponseMessage.java
index 19c4d98..b0dbf0b 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseMessage.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/ResponseMessage.java
@@ -16,10 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.message;
+package org.apache.tinkerpop.gremlin.util.message;
 
 import org.apache.commons.lang3.exception.ExceptionUtils;
-import org.apache.tinkerpop.gremlin.driver.Tokens;
+import org.apache.tinkerpop.gremlin.util.Tokens;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 
 import java.util.Collections;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseResult.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/ResponseResult.java
similarity index 96%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseResult.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/ResponseResult.java
index 988de82..9cf5a6c 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseResult.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/ResponseResult.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.message;
+package org.apache.tinkerpop.gremlin.util.message;
 
 import java.util.Map;
 
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseStatus.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/ResponseStatus.java
similarity index 97%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseStatus.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/ResponseStatus.java
index ad9a36e..dbc2995 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseStatus.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/ResponseStatus.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.message;
+package org.apache.tinkerpop.gremlin.util.message;
 
 import java.util.Map;
 
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseStatusCode.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/ResponseStatusCode.java
similarity index 98%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseStatusCode.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/ResponseStatusCode.java
index a87c640..98c727e 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseStatusCode.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/ResponseStatusCode.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.message;
+package org.apache.tinkerpop.gremlin.util.message;
 
 import org.apache.tinkerpop.gremlin.process.traversal.Failure;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/AbstractGraphSONMessageSerializerV1d0.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/AbstractGraphSONMessageSerializerV1d0.java
similarity index 97%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/AbstractGraphSONMessageSerializerV1d0.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/AbstractGraphSONMessageSerializerV1d0.java
index ca96ee5..8a33ce5 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/AbstractGraphSONMessageSerializerV1d0.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/AbstractGraphSONMessageSerializerV1d0.java
@@ -16,11 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
-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.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
 import io.netty.buffer.ByteBuf;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/AbstractGraphSONMessageSerializerV2d0.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/AbstractGraphSONMessageSerializerV2d0.java
similarity index 97%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/AbstractGraphSONMessageSerializerV2d0.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/AbstractGraphSONMessageSerializerV2d0.java
index 69aee63..db82698 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/AbstractGraphSONMessageSerializerV2d0.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/AbstractGraphSONMessageSerializerV2d0.java
@@ -16,14 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
 import io.netty.util.ReferenceCountUtil;
-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.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.AbstractObjectDeserializer;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/AbstractMessageSerializer.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/AbstractMessageSerializer.java
similarity index 96%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/AbstractMessageSerializer.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/AbstractMessageSerializer.java
index 50124a6..74ecc18 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/AbstractMessageSerializer.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/AbstractMessageSerializer.java
@@ -16,9 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
 import org.apache.tinkerpop.gremlin.structure.io.IoRegistry;
 import org.apache.tinkerpop.gremlin.structure.io.Mapper;
 
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphBinaryMessageSerializerV1.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphBinaryMessageSerializerV1.java
similarity index 96%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphBinaryMessageSerializerV1.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphBinaryMessageSerializerV1.java
index 1c7a69a..28adcf3 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphBinaryMessageSerializerV1.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphBinaryMessageSerializerV1.java
@@ -16,19 +16,19 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
 import io.netty.buffer.Unpooled;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryIo;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryMapper;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter;
-import org.apache.tinkerpop.gremlin.driver.ser.binary.RequestMessageSerializer;
-import org.apache.tinkerpop.gremlin.driver.ser.binary.ResponseMessageSerializer;
+import org.apache.tinkerpop.gremlin.util.ser.binary.RequestMessageSerializer;
+import org.apache.tinkerpop.gremlin.util.ser.binary.ResponseMessageSerializer;
 import org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry;
 import org.apache.tinkerpop.gremlin.structure.io.binary.types.CustomTypeSerializer;
 import org.apache.tinkerpop.gremlin.structure.Graph;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerGremlinV1d0.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerGremlinV1d0.java
similarity index 97%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerGremlinV1d0.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerGremlinV1d0.java
index ef9e0ef..52e58db 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerGremlinV1d0.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerGremlinV1d0.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerGremlinV2d0.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerGremlinV2d0.java
similarity index 98%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerGremlinV2d0.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerGremlinV2d0.java
index 9230e6c..29e3cea 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerGremlinV2d0.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerGremlinV2d0.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONXModuleV2d0;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV1d0.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV1d0.java
similarity index 94%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV1d0.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV1d0.java
index 60a2486..c1291bf 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV1d0.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV1d0.java
@@ -16,12 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import io.netty.buffer.ByteBufAllocator;
-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.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.TypeInfo;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV2d0.java
similarity index 94%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV2d0.java
index 3442205..d0a434a 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV2d0.java
@@ -16,12 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import io.netty.buffer.ByteBufAllocator;
-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.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONXModuleV2d0;
@@ -31,8 +31,6 @@
 import org.slf4j.LoggerFactory;
 
 import java.nio.ByteBuffer;
-import java.util.Map;
-import java.util.UUID;
 
 /**
  * Serialize results to JSON with version 2.0.x schema and the extended module.
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV3d0.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV3d0.java
similarity index 96%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV3d0.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV3d0.java
index 5aebf77..8021392 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV3d0.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV3d0.java
@@ -16,11 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import io.netty.buffer.ByteBufAllocator;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONXModuleV3d0;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/MessageTextSerializer.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/MessageTextSerializer.java
similarity index 87%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/MessageTextSerializer.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/MessageTextSerializer.java
index 6ef0885..7d46aab 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/MessageTextSerializer.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/MessageTextSerializer.java
@@ -16,12 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import io.netty.buffer.ByteBufAllocator;
-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.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
 
 /**
  * An extension to the MessageSerializer interface that allows a format to be compatible with text-based
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/NettyBuffer.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/NettyBuffer.java
similarity index 98%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/NettyBuffer.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/NettyBuffer.java
index 5aecac2..3310313 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/NettyBuffer.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/NettyBuffer.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import io.netty.buffer.ByteBuf;
 import org.apache.tinkerpop.gremlin.structure.io.Buffer;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/NettyBufferFactory.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/NettyBufferFactory.java
similarity index 98%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/NettyBufferFactory.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/NettyBufferFactory.java
index 46ef31b..5626f4c 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/NettyBufferFactory.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/NettyBufferFactory.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/RequestMessageGryoSerializer.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/RequestMessageGryoSerializer.java
similarity index 94%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/RequestMessageGryoSerializer.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/RequestMessageGryoSerializer.java
index 6622dca..8b0c30b 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/RequestMessageGryoSerializer.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/RequestMessageGryoSerializer.java
@@ -16,9 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.structure.io.gryo.kryoshim.InputShim;
 import org.apache.tinkerpop.gremlin.structure.io.gryo.kryoshim.KryoShim;
 import org.apache.tinkerpop.gremlin.structure.io.gryo.kryoshim.OutputShim;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/ResponseMessageGryoSerializer.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/ResponseMessageGryoSerializer.java
similarity index 93%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/ResponseMessageGryoSerializer.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/ResponseMessageGryoSerializer.java
index 8e02982..84392a9 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/ResponseMessageGryoSerializer.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/ResponseMessageGryoSerializer.java
@@ -16,10 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.structure.io.gryo.kryoshim.InputShim;
 import org.apache.tinkerpop.gremlin.structure.io.gryo.kryoshim.KryoShim;
 import org.apache.tinkerpop.gremlin.structure.io.gryo.kryoshim.OutputShim;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/SerTokens.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/SerTokens.java
similarity index 97%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/SerTokens.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/SerTokens.java
index 5e0c292..bbc1a5e 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/SerTokens.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/SerTokens.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.HaltedTraverserStrategy;
 
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/SerializationException.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/SerializationException.java
similarity index 95%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/SerializationException.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/SerializationException.java
index be555da..1b5bb6f 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/SerializationException.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/SerializationException.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import java.io.IOException;
 
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/Serializers.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/Serializers.java
similarity index 94%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/Serializers.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/Serializers.java
index 334467a..aea0369 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/Serializers.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/Serializers.java
@@ -16,9 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.HaltedTraverserStrategy;
 
 /**
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/RequestMessageSerializer.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/binary/RequestMessageSerializer.java
similarity index 92%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/RequestMessageSerializer.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/binary/RequestMessageSerializer.java
index 004bfe9..9fecfc3 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/RequestMessageSerializer.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/binary/RequestMessageSerializer.java
@@ -16,12 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser.binary;
+package org.apache.tinkerpop.gremlin.util.ser.binary;
 
 import io.netty.buffer.ByteBuf;
-import org.apache.tinkerpop.gremlin.driver.ser.NettyBufferFactory;
-import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
-import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
+import org.apache.tinkerpop.gremlin.util.ser.NettyBufferFactory;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
 import org.apache.tinkerpop.gremlin.structure.io.Buffer;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/ResponseMessageSerializer.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/binary/ResponseMessageSerializer.java
similarity index 88%
rename from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/ResponseMessageSerializer.java
rename to gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/binary/ResponseMessageSerializer.java
index 5a07cdb..f6cc304 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/ResponseMessageSerializer.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/binary/ResponseMessageSerializer.java
@@ -16,15 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser.binary;
+package org.apache.tinkerpop.gremlin.util.ser.binary;
 
 import io.netty.buffer.ByteBuf;
-import org.apache.tinkerpop.gremlin.driver.ser.NettyBufferFactory;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseResult;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatus;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
-import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
+import org.apache.tinkerpop.gremlin.util.ser.NettyBufferFactory;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseResult;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatus;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
 import org.apache.tinkerpop.gremlin.structure.io.Buffer;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter;
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/MockitoHamcrestMatcherAdapter.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/MockitoHamcrestMatcherAdapter.java
similarity index 97%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/MockitoHamcrestMatcherAdapter.java
rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/MockitoHamcrestMatcherAdapter.java
index 252d9a9..a99f4ab 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/MockitoHamcrestMatcherAdapter.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/MockitoHamcrestMatcherAdapter.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver;
+package org.apache.tinkerpop.gremlin.util;
 
 import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/message/ResponseStatusCodeTest.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/message/ResponseStatusCodeTest.java
similarity index 95%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/message/ResponseStatusCodeTest.java
rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/message/ResponseStatusCodeTest.java
index 3fc8a78..235eddd 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/message/ResponseStatusCodeTest.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/message/ResponseStatusCodeTest.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.tinkerpop.gremlin.driver.message;
+package org.apache.tinkerpop.gremlin.util.message;
 
 import org.junit.Test;
 
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/AbstractRoundTripTest.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/AbstractRoundTripTest.java
similarity index 96%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/AbstractRoundTripTest.java
rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/AbstractRoundTripTest.java
index f5202f9..18dfa1a 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/AbstractRoundTripTest.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/AbstractRoundTripTest.java
@@ -16,9 +16,8 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
-import io.netty.buffer.ByteBufAllocator;
 import org.apache.tinkerpop.gremlin.process.computer.Computer;
 import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.VertexProgramStrategy;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
@@ -33,17 +32,13 @@
 import org.apache.tinkerpop.gremlin.process.traversal.util.MutableMetrics;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
 import org.apache.tinkerpop.gremlin.structure.*;
-import org.apache.tinkerpop.gremlin.structure.io.Buffer;
 import org.apache.tinkerpop.gremlin.structure.io.IoTest;
-import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader;
-import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter;
 import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceEdge;
 import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceProperty;
 import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceVertex;
 import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceVertexProperty;
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
 import org.apache.tinkerpop.gremlin.util.function.Lambda;
-import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 
@@ -58,8 +53,8 @@
 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.apache.tinkerpop.gremlin.util.MockitoHamcrestMatcherAdapter.reflectionEquals;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
 
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerGremlinV1d0Test.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerGremlinV1d0Test.java
similarity index 97%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerGremlinV1d0Test.java
rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerGremlinV1d0Test.java
index 8cba236..8c2f1c8 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerGremlinV1d0Test.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerGremlinV1d0Test.java
@@ -16,14 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
 import io.netty.buffer.UnpooledByteBufAllocator;
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Graph;
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerGremlinV2d0Test.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerGremlinV2d0Test.java
similarity index 96%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerGremlinV2d0Test.java
rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerGremlinV2d0Test.java
index 2c781cf..7e993bf 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerGremlinV2d0Test.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerGremlinV2d0Test.java
@@ -16,15 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
 import io.netty.buffer.UnpooledByteBufAllocator;
-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.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
 import org.apache.tinkerpop.gremlin.structure.Edge;
@@ -50,7 +50,7 @@
 import java.util.Map;
 import java.util.UUID;
 
-import static org.apache.tinkerpop.gremlin.driver.ser.AbstractGraphSONMessageSerializerV2d0.ResponseMessageDeserializer;
+import static org.apache.tinkerpop.gremlin.util.ser.AbstractGraphSONMessageSerializerV2d0.ResponseMessageDeserializer;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV1d0Test.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV1d0Test.java
similarity index 98%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV1d0Test.java
rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV1d0Test.java
index 001ce7e..d5d3d24 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV1d0Test.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV1d0Test.java
@@ -16,12 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import io.netty.buffer.ByteBufAllocator;
-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.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
 import org.apache.tinkerpop.gremlin.structure.Edge;
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0Test.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV2d0Test.java
similarity index 98%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0Test.java
rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV2d0Test.java
index 3d01af4..2a0bf47 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0Test.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV2d0Test.java
@@ -16,15 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
 import io.netty.buffer.UnpooledByteBufAllocator;
-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.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
 import org.apache.tinkerpop.gremlin.structure.Edge;
@@ -529,7 +529,7 @@
         final Graph graph = TinkerFactory.createModern();
 
         final ResponseMessage responseMessage = ResponseMessage.build(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).
-                code(org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode.SUCCESS).
+                code(org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode.SUCCESS).
                 result(Collections.singletonList(graph.vertices().next())).create();
 
         final String respJson = om.writeValueAsString(responseMessage);
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV3d0RoundTripTest.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV3d0RoundTripTest.java
similarity index 94%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV3d0RoundTripTest.java
rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV3d0RoundTripTest.java
index e0760fc..c6b53ec 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV3d0RoundTripTest.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV3d0RoundTripTest.java
@@ -16,12 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
 import io.netty.buffer.UnpooledByteBufAllocator;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
 import org.junit.Test;
 
 import java.util.Arrays;
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV3d0Test.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV3d0Test.java
similarity index 97%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV3d0Test.java
rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV3d0Test.java
index 701e2cd..5b54157 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV3d0Test.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV3d0Test.java
@@ -16,15 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
 import io.netty.buffer.UnpooledByteBufAllocator;
-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.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.MessageSerializer;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
 import org.apache.tinkerpop.gremlin.structure.Edge;
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/NettyBufferFactoryTest.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/NettyBufferFactoryTest.java
similarity index 98%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/NettyBufferFactoryTest.java
rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/NettyBufferFactoryTest.java
index 223b289..9e2e1a1 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/NettyBufferFactoryTest.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/NettyBufferFactoryTest.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.tinkerpop.gremlin.driver.ser;
+package org.apache.tinkerpop.gremlin.util.ser;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
@@ -27,7 +27,6 @@
 import org.junit.AfterClass;
 import org.junit.Test;
 
-import java.io.IOException;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryMessageSerializerV1Test.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryMessageSerializerV1Test.java
similarity index 93%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryMessageSerializerV1Test.java
rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryMessageSerializerV1Test.java
index 6cd37b8..c4b486f 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryMessageSerializerV1Test.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryMessageSerializerV1Test.java
@@ -16,15 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser.binary;
+package org.apache.tinkerpop.gremlin.util.ser.binary;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
-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.driver.ser.GraphBinaryMessageSerializerV1;
-import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
+import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
 import org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry;
 import org.junit.Test;
 
@@ -34,7 +34,7 @@
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import static org.apache.tinkerpop.gremlin.driver.MockitoHamcrestMatcherAdapter.reflectionEquals;
+import static org.apache.tinkerpop.gremlin.util.MockitoHamcrestMatcherAdapter.reflectionEquals;
 import static org.junit.Assert.assertEquals;
 import static org.hamcrest.MatcherAssert.assertThat;
 
@@ -142,7 +142,7 @@
         final Map<String, Object> config = new HashMap<>();
         int counter = SampleTypeSerializerRegistryBuilder.createCounter.get();
 
-        config.put(GraphBinaryMessageSerializerV1.TOKEN_BUILDER, "org.apache.tinkerpop.gremlin.driver.ser.binary.GraphBinaryMessageSerializerV1Test$SampleTypeSerializerRegistryBuilder");
+        config.put(GraphBinaryMessageSerializerV1.TOKEN_BUILDER, "org.apache.tinkerpop.gremlin.util.ser.binary.GraphBinaryMessageSerializerV1Test$SampleTypeSerializerRegistryBuilder");
         serializer.configure(config, null);
 
         counter = SampleTypeSerializerRegistryBuilder.createCounter.get() - counter;
@@ -154,7 +154,7 @@
     public void shouldThrowWhenConfigurationOfRegistryBuilderFails() {
         final GraphBinaryMessageSerializerV1 serializer = new GraphBinaryMessageSerializerV1();
         final Map<String, Object> config = new HashMap<>();
-        config.put(GraphBinaryMessageSerializerV1.TOKEN_BUILDER, "org.apache.tinkerpop.gremlin.driver.ser.binary.NonExistentClass");
+        config.put(GraphBinaryMessageSerializerV1.TOKEN_BUILDER, "org.apache.tinkerpop.gremlin.util.ser.binary.NonExistentClass");
 
         serializer.configure(config, null);
     }
diff --git a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryReaderWriterRoundTripTest.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryReaderWriterRoundTripTest.java
new file mode 100644
index 0000000..d34c88e
--- /dev/null
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryReaderWriterRoundTripTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.ser.binary;
+
+import io.netty.buffer.ByteBufAllocator;
+import org.apache.tinkerpop.gremlin.util.ser.AbstractRoundTripTest;
+import org.apache.tinkerpop.gremlin.util.ser.NettyBufferFactory;
+import org.apache.tinkerpop.gremlin.structure.io.Buffer;
+import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader;
+import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter;
+import org.junit.Test;
+import java.util.*;
+import java.util.function.Consumer;
+
+import static org.junit.Assert.assertEquals;
+
+public class GraphBinaryReaderWriterRoundTripTest extends AbstractRoundTripTest {
+    private final GraphBinaryWriter writer = new GraphBinaryWriter();
+    private final GraphBinaryReader reader = new GraphBinaryReader();
+    private final ByteBufAllocator allocator = ByteBufAllocator.DEFAULT;
+    private static NettyBufferFactory bufferFactory = new NettyBufferFactory();
+
+    private static List<String> skippedTests
+            = Arrays.asList("ReferenceVertexProperty");
+
+    @Test
+    public void shouldWriteAndRead() throws Exception {
+        // some tests are not valid for graphbinary
+        if (skippedTests.contains(name)) return;
+
+        // Test it multiple times as the type registry might change its internal state
+        for (int i = 0; i < 5; i++) {
+            final Buffer buffer = bufferFactory.create(allocator.buffer());
+            writer.write(value, buffer);
+            buffer.readerIndex(0);
+            final Object result = reader.read(buffer);
+
+            Optional.ofNullable(assertion).orElse((Consumer) r -> assertEquals(value, r)).accept(result);
+        }
+    }
+}
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializerFailureTests.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/TypeSerializerFailureTests.java
similarity index 97%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializerFailureTests.java
rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/TypeSerializerFailureTests.java
index 2268bf1..d41074e 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializerFailureTests.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/TypeSerializerFailureTests.java
@@ -17,10 +17,10 @@
  * under the License.
  */
 
-package org.apache.tinkerpop.gremlin.driver.ser.binary;
+package org.apache.tinkerpop.gremlin.util.ser.binary;
 
 import io.netty.buffer.UnpooledByteBufAllocator;
-import org.apache.tinkerpop.gremlin.driver.ser.NettyBufferFactory;
+import org.apache.tinkerpop.gremlin.util.ser.NettyBufferFactory;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializerRegistryTest.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/TypeSerializerRegistryTest.java
similarity index 95%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializerRegistryTest.java
rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/TypeSerializerRegistryTest.java
index a40285b..fbdaa2e 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializerRegistryTest.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/TypeSerializerRegistryTest.java
@@ -16,10 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser.binary;
+package org.apache.tinkerpop.gremlin.util.ser.binary;
 
-import org.apache.tinkerpop.gremlin.driver.ser.binary.types.sample.SamplePerson;
-import org.apache.tinkerpop.gremlin.driver.ser.binary.types.sample.SamplePersonSerializer;
+import org.apache.tinkerpop.gremlin.util.ser.binary.types.sample.SamplePerson;
+import org.apache.tinkerpop.gremlin.util.ser.binary.types.sample.SamplePersonSerializer;
 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;
@@ -98,7 +98,7 @@
             message = ex.getMessage();
         }
 
-        assertEquals("Serializer for type org.apache.tinkerpop.gremlin.driver.ser.binary.types.sample.SamplePerson not found", message);
+        assertEquals("Serializer for type org.apache.tinkerpop.gremlin.util.ser.binary.types.sample.SamplePerson not found", message);
         assertEquals(1, called[0]);
     }
 
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/CharSerializerTest.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/CharSerializerTest.java
similarity index 95%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/CharSerializerTest.java
rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/CharSerializerTest.java
index 4d38c99..f5d6823 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/CharSerializerTest.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/CharSerializerTest.java
@@ -16,12 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser.binary.types;
+package org.apache.tinkerpop.gremlin.util.ser.binary.types;
 
 import io.netty.buffer.ByteBufAllocator;
 import io.netty.buffer.Unpooled;
 import io.netty.buffer.UnpooledByteBufAllocator;
-import org.apache.tinkerpop.gremlin.driver.ser.NettyBufferFactory;
+import org.apache.tinkerpop.gremlin.util.ser.NettyBufferFactory;
 import org.apache.tinkerpop.gremlin.structure.io.Buffer;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter;
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/sample/SamplePerson.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/sample/SamplePerson.java
similarity index 94%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/sample/SamplePerson.java
rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/sample/SamplePerson.java
index fd4d05a..2970dce 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/sample/SamplePerson.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/sample/SamplePerson.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser.binary.types.sample;
+package org.apache.tinkerpop.gremlin.util.ser.binary.types.sample;
 
 import java.util.Date;
 import java.util.Objects;
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/sample/SamplePersonSerializer.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/sample/SamplePersonSerializer.java
similarity index 96%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/sample/SamplePersonSerializer.java
rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/sample/SamplePersonSerializer.java
index ad9e5db..2a76206 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/sample/SamplePersonSerializer.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/sample/SamplePersonSerializer.java
@@ -16,9 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser.binary.types.sample;
+package org.apache.tinkerpop.gremlin.util.ser.binary.types.sample;
 
-import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
+import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
 import org.apache.tinkerpop.gremlin.structure.io.Buffer;
 import org.apache.tinkerpop.gremlin.structure.io.binary.DataType;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader;
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/sample/SamplePersonSerializerTest.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/sample/SamplePersonSerializerTest.java
similarity index 89%
rename from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/sample/SamplePersonSerializerTest.java
rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/sample/SamplePersonSerializerTest.java
index 7ff130e..c17e976 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/sample/SamplePersonSerializerTest.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/sample/SamplePersonSerializerTest.java
@@ -16,13 +16,13 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.driver.ser.binary.types.sample;
+package org.apache.tinkerpop.gremlin.util.ser.binary.types.sample;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
-import org.apache.tinkerpop.gremlin.driver.ser.NettyBufferFactory;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1;
+import org.apache.tinkerpop.gremlin.util.ser.NettyBufferFactory;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
 import org.apache.tinkerpop.gremlin.structure.io.AbstractIoRegistry;
 import org.apache.tinkerpop.gremlin.structure.io.Buffer;
 import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryIo;
@@ -40,9 +40,9 @@
 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.apache.tinkerpop.gremlin.util.MockitoHamcrestMatcherAdapter.reflectionEquals;
+import static org.apache.tinkerpop.gremlin.util.ser.AbstractMessageSerializer.TOKEN_IO_REGISTRIES;
+import static org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1.TOKEN_CUSTOM;
 import static org.hamcrest.MatcherAssert.assertThat;
 
 public class SamplePersonSerializerTest {
diff --git a/gremlint/package-lock.json b/gremlint/package-lock.json
index a7c7785..a003207 100644
--- a/gremlint/package-lock.json
+++ b/gremlint/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "gremlint",
-  "version": "3.6.5-alpha1",
+  "version": "3.7.0-alpha1",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "gremlint",
-      "version": "3.6.5-alpha1",
+      "version": "3.7.0-alpha1",
       "license": "Apache-2.0",
       "devDependencies": {
         "@types/jest": "^27.5.0",
diff --git a/gremlint/package.json b/gremlint/package.json
index e6ee1c8..b0cf6ce 100644
--- a/gremlint/package.json
+++ b/gremlint/package.json
@@ -1,6 +1,6 @@
 {
   "name": "gremlint",
-  "version": "3.6.5-alpha1",
+  "version": "3.7.0-alpha1",
   "description": "Linter/code formatter for Gremlin",
   "main": "lib/index.js",
   "types": "lib/index.d.ts",
diff --git a/gremlint/pom.xml b/gremlint/pom.xml
index f001f63..eec474e 100644
--- a/gremlint/pom.xml
+++ b/gremlint/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>tinkerpop</artifactId>
-        <version>3.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>gremlint</artifactId>
     <name>Apache TinkerPop :: Gremlint</name>
@@ -53,7 +53,7 @@
                 <artifactId>gmavenplus-plugin</artifactId>
                 <dependencies>
                     <dependency>
-                        <groupId>org.codehaus.groovy</groupId>
+                        <groupId>org.apache.groovy</groupId>
                         <artifactId>groovy-all</artifactId>
                         <version>${groovy.version}</version>
                         <type>pom</type>
diff --git a/hadoop-gremlin/pom.xml b/hadoop-gremlin/pom.xml
index c4a59bc..baa6882 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.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>hadoop-gremlin</artifactId>
     <name>Apache TinkerPop :: Hadoop Gremlin</name>
@@ -140,21 +140,21 @@
             <artifactId>commons-logging</artifactId>
             <version>1.2</version>
         </dependency>
-        <!-- use jackson 2.12.3 to fit better with spark where Scala module 2.12.3 requires Jackson Databind version >= 2.12.0 and < 2.13.0 -->
+        <!-- use jackson 2.13.5 to fit better with spark where Scala module 2.13.4 requires Jackson Databind version >= 2.13.0 and < 2.14.0 -->
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-annotations</artifactId>
-            <version>2.12.7</version>
+            <version>2.13.5</version>
         </dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-core</artifactId>
-            <version>2.12.7</version>
+            <version>2.13.5</version>
         </dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-databind</artifactId>
-            <version>2.12.7</version>
+            <version>2.13.5</version>
         </dependency>
         <!-- TEST -->
         <dependency>
@@ -204,13 +204,6 @@
                         <manifestEntries>
                             <Gremlin-Plugin-Dependencies>org.apache.hadoop:hadoop-client:${hadoop.version}
                             </Gremlin-Plugin-Dependencies>
-                            <!-- initialization failures for using jackson after 2.12.* and hadoop pulls these in -->
-                            <Gremlin-Plugin-Paths>
-                                jackson-annotations-2.13.2.jar=;jackson-databind-2.13.2.2.jar=;jackson-core-2.13.2.jar=
-                            </Gremlin-Plugin-Paths>
-                            <Gremlin-Lib-Paths>
-                                jackson-annotations-2.13.2.jar=;jackson-databind-2.13.2.2.jar=;jackson-core-2.13.2.jar=
-                            </Gremlin-Lib-Paths>
                         </manifestEntries>
                     </archive>
                 </configuration>
diff --git a/licenses/wow b/licenses/wow
new file mode 100644
index 0000000..c7a091e
--- /dev/null
+++ b/licenses/wow
@@ -0,0 +1,7 @@
+Copyright (C) 2014; Matthieu Aussaguel
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/neo4j-gremlin/pom.xml b/neo4j-gremlin/pom.xml
index 4b2f64e..c5b1516 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.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>neo4j-gremlin</artifactId>
     <name>Apache TinkerPop :: Neo4j Gremlin</name>
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 b5fa2af..5ea926d 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,7 +93,7 @@
 
     @Override
     public <U> Iterator<Property<U>> properties(final String... propertyKeys) {
-        throw VertexProperty.Exceptions.metaPropertiesNotSupported();
+        return Collections.emptyIterator();
     }
 
     @Override
diff --git a/pom.xml b/pom.xml
index f733e18..5fa2413 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,11 +21,11 @@
     <parent>
         <groupId>org.apache</groupId>
         <artifactId>apache</artifactId>
-        <version>21</version>
+        <version>27</version>
     </parent>
     <groupId>org.apache.tinkerpop</groupId>
     <artifactId>tinkerpop</artifactId>
-    <version>3.6.5-SNAPSHOT</version>
+    <version>3.7.0-SNAPSHOT</version>
     <packaging>pom</packaging>
     <name>Apache TinkerPop</name>
     <description>A Graph Computing Framework</description>
@@ -143,6 +143,7 @@
         <module>gremlin-archetype</module>
         <module>gremlin-tools</module>
         <module>gremlint</module>
+        <module>gremlin-util</module>
     </modules>
     <scm>
         <connection>scm:git:git@github.com:apache/tinkerpop.git</connection>
@@ -156,11 +157,11 @@
         <commons.configuration.version>2.9.0</commons.configuration.version>
         <commons.lang.version>2.6</commons.lang.version>
         <commons.io.version>2.8.0</commons.io.version>
-        <commons.lang3.version>3.11</commons.lang3.version>
+        <commons.lang3.version>3.12.0</commons.lang3.version>
         <commons.text.version>1.10.0</commons.text.version>
         <cucumber.version>6.11.0</cucumber.version>
         <exp4j.version>0.4.8</exp4j.version>
-        <groovy.version>2.5.22</groovy.version>
+        <groovy.version>4.0.9</groovy.version>
         <guice.version>4.2.3</guice.version>
         <hadoop.version>3.3.3</hadoop.version>
         <hamcrest.version>2.2</hamcrest.version>
@@ -173,12 +174,11 @@
         <kerby.version>2.0.1</kerby.version>
         <logback.version>1.2.11</logback.version>
         <metrics.version>3.0.2</metrics.version>
-        <mockito.version>3.3.3</mockito.version>
+        <mockito.version>4.10.0</mockito.version>
         <netty.version>4.1.86.Final</netty.version>
         <slf4j.version>1.7.25</slf4j.version>
         <snakeyaml.version>2.0</snakeyaml.version>
-        <spark.version>3.2.1</spark.version>
-        <powermock.version>2.0.9</powermock.version>
+        <spark.version>3.3.2</spark.version>
 
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
@@ -198,6 +198,28 @@
         <log4j-silent.properties>file:target/test-classes/log4j-silent.properties</log4j-silent.properties>
 
         <muteTestLogs>false</muteTestLogs>
+
+        <!--
+        These options are necessary to run and pass the tests with JDK 17. There are some unexported APIs that we need
+        access to and we still rely on libraries that use deep reflection (notably Kryo). We can probably remove this
+        in the future when we don't need reflection and we turn this into a JPMS module.
+        -->
+        <jdk17JvmArgs>
+            -XX:+IgnoreUnrecognizedVMOptions
+            --add-exports=java.base/sun.nio.ch=ALL-UNNAMED
+            --add-exports=java.base/sun.security.x509=ALL-UNNAMED
+            --add-exports=java.base/sun.security.action=ALL-UNNAMED
+            --add-opens=java.base/java.io=ALL-UNNAMED
+            --add-opens=java.base/java.nio=ALL-UNNAMED
+            --add-opens=java.base/sun.nio.cs=ALL-UNNAMED
+            --add-opens=java.base/java.lang=ALL-UNNAMED
+            --add-opens=java.base/java.lang.invoke=ALL-UNNAMED
+            --add-opens=java.base/java.lang.reflect=ALL-UNNAMED
+            --add-opens=java.base/java.util=ALL-UNNAMED
+            --add-opens=java.base/java.util.concurrent=ALL-UNNAMED
+            --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED
+            --add-opens=java.base/java.net=ALL-UNNAMED
+        </jdk17JvmArgs>
     </properties>
     <build>
         <directory>${basedir}/target</directory>
@@ -224,7 +246,7 @@
                             <rules>
                                 <DependencyConvergence/>
                                 <requireJavaVersion>
-                                    <version>[1.8,12)</version>
+                                    <version>[1.8,18)</version>
                                 </requireJavaVersion>
                                 <requireMavenVersion>
                                     <version>[3.5.3,)</version>
@@ -417,6 +439,7 @@
                         <manifestEntries>
                             <version>${project.version}</version>
                             <hash>${buildNumber}</hash>
+                            <tinkerpop-version>${project.version}</tinkerpop-version>
                         </manifestEntries>
                     </archive>
                 </configuration>
@@ -452,6 +475,7 @@
                         <exclude>data/*.txt</exclude>
                         <exclude>**/bin/gremlin.sh</exclude>
                         <exclude>docs/static/**</exclude>
+                        <exclude>docs/original/**</exclude>
                         <exclude>docs/site/home/css/**</exclude>
                         <exclude>docs/site/home/js/**</exclude>
                         <exclude>docs/gremlint/build/**</exclude>
@@ -553,7 +577,7 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-deploy-plugin</artifactId>
-                    <version>2.8.2</version>
+                    <version>3.0.0</version>
                 </plugin>
                 <!-- reverted surefire to 2.21.0 for performance reasons. 2.22.2 required forkCount=1 and
                      reuseForks=true which seemed to more the double the build time. there are only milestone
@@ -580,6 +604,7 @@
                             -Dlog4j.configuration=${log4j-test.properties}
                             -Dbuild.dir=${project.build.directory}
                             -Dis.testing=true -Djava.net.preferIPv4Stack=true ${suresafeArgs}
+                            ${jdk17JvmArgs}
                         </argLine>
                         <trimStackTrace>false</trimStackTrace>
                         <excludes>
@@ -608,6 +633,7 @@
                                     -Dhost=localhost -Dport=8182
                                     -Dbuild.dir=${project.build.directory} -Dis.testing=true
                                     -Djava.net.preferIPv4Stack=true ${suresafeArgs}
+                                    ${jdk17JvmArgs}
                                 </argLine>
                                 <forkCount>1</forkCount>
                                 <reuseForks>false</reuseForks>
@@ -653,7 +679,7 @@
                 <plugin>
                     <groupId>org.codehaus.gmavenplus</groupId>
                     <artifactId>gmavenplus-plugin</artifactId>
-                    <version>1.13.1</version>
+                    <version>2.1.0</version>
                     <configuration>
                         <targetBytecode>1.8</targetBytecode>
                     </configuration>
@@ -824,41 +850,7 @@
             <dependency>
                 <groupId>org.objenesis</groupId>
                 <artifactId>objenesis</artifactId>
-                <version>2.4</version>
-            </dependency>
-            <dependency>
-                <groupId>org.powermock</groupId>
-                <artifactId>powermock-module-junit4</artifactId>
-                <version>${powermock.version}</version>
-                <scope>test</scope>
-                <exclusions>
-                    <!-- conflict with mockito - excluding from the mockito side doesn't work -->
-                    <exclusion>
-                        <groupId>net.bytebuddy</groupId>
-                        <artifactId>byte-buddy</artifactId>
-                    </exclusion>
-                    <exclusion>
-                        <groupId>net.bytebuddy</groupId>
-                        <artifactId>byte-buddy-agent</artifactId>
-                    </exclusion>
-                </exclusions>
-            </dependency>
-            <dependency>
-                <groupId>org.powermock</groupId>
-                <artifactId>powermock-api-mockito2</artifactId>
-                <version>${powermock.version}</version>
-                <scope>test</scope>
-                <exclusions>
-                    <!-- conflict with mockito - excluding from the mockito side doesn't work -->
-                    <exclusion>
-                        <groupId>net.bytebuddy</groupId>
-                        <artifactId>byte-buddy</artifactId>
-                    </exclusion>
-                    <exclusion>
-                        <groupId>net.bytebuddy</groupId>
-                        <artifactId>byte-buddy-agent</artifactId>
-                    </exclusion>
-                </exclusions>
+                <version>3.3</version>
             </dependency>
             <dependency>
                 <groupId>org.hamcrest</groupId>
@@ -907,7 +899,7 @@
         <profile>
             <id>jdk11</id>
             <activation>
-                <jdk>11</jdk>
+                <jdk>[11,18)</jdk>
             </activation>
             <properties>
                 <suresafeArgs>--illegal-access=permit</suresafeArgs>
@@ -1557,28 +1549,24 @@
                                             <version>${project.version}</version>
                                         </additionalDependency>
                                         <additionalDependency>
-                                            <groupId>org.codehaus.groovy</groupId>
+                                            <groupId>org.apache.groovy</groupId>
                                             <artifactId>groovy</artifactId>
                                             <version>${groovy.version}</version>
-                                            <classifier>indy</classifier>
                                         </additionalDependency>
                                         <additionalDependency>
-                                            <groupId>org.codehaus.groovy</groupId>
+                                            <groupId>org.apache.groovy</groupId>
                                             <artifactId>groovy-jsr223</artifactId>
                                             <version>${groovy.version}</version>
-                                            <classifier>indy</classifier>
                                         </additionalDependency>
                                         <additionalDependency>
-                                            <groupId>org.codehaus.groovy</groupId>
+                                            <groupId>org.apache.groovy</groupId>
                                             <artifactId>groovy-groovysh</artifactId>
                                             <version>${groovy.version}</version>
-                                            <classifier>indy</classifier>
                                         </additionalDependency>
                                         <additionalDependency>
-                                            <groupId>org.codehaus.groovy</groupId>
+                                            <groupId>org.apache.groovy</groupId>
                                             <artifactId>groovy-json</artifactId>
                                             <version>${groovy.version}</version>
-                                            <classifier>indy</classifier>
                                         </additionalDependency>
                                         <additionalDependency>
                                             <groupId>org.apache.commons</groupId>
@@ -1775,16 +1763,14 @@
                                             <version>${project.version}</version>
                                         </additionalDependency>
                                         <additionalDependency>
-                                            <groupId>org.codehaus.groovy</groupId>
+                                            <groupId>org.apache.groovy</groupId>
                                             <artifactId>groovy-groovysh</artifactId>
                                             <version>${groovy.version}</version>
-                                            <classifier>indy</classifier>
                                         </additionalDependency>
                                         <additionalDependency>
-                                            <groupId>org.codehaus.groovy</groupId>
+                                            <groupId>org.apache.groovy</groupId>
                                             <artifactId>groovy-json</artifactId>
                                             <version>${groovy.version}</version>
-                                            <classifier>indy</classifier>
                                         </additionalDependency>
                                         <additionalDependency>
                                             <groupId>org.apache.commons</groupId>
@@ -1900,6 +1886,7 @@
                                 -Dlog4j.configuration=${log4j-silent.properties}
                                 -Dbuild.dir=${project.build.directory} -Dis.testing=true
                                 -Djava.net.preferIPv4Stack=true ${suresafeArgs}
+                                ${jdk17JvmArgs}
                             </argLine>
                             <excludes>
                                 <exclude>**/*IntegrateTest.java</exclude>
diff --git a/spark-gremlin/pom.xml b/spark-gremlin/pom.xml
index 631908a..66ad8d7 100644
--- a/spark-gremlin/pom.xml
+++ b/spark-gremlin/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.apache.tinkerpop</groupId>
         <artifactId>tinkerpop</artifactId>
-        <version>3.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>spark-gremlin</artifactId>
     <name>Apache TinkerPop :: Spark Gremlin</name>
@@ -74,6 +74,11 @@
                     <groupId>com.fasterxml.jackson.core</groupId>
                     <artifactId>jackson-core</artifactId>
                 </exclusion>
+                <!-- Spark requires a specific range of jackson-databind. See dependency section below. -->
+                <exclusion>
+                    <groupId>com.fasterxml.jackson.core</groupId>
+                    <artifactId>jackson-databind</artifactId>
+                </exclusion>
                 <exclusion>
                     <groupId>org.apache.commons</groupId>
                     <artifactId>commons-math3</artifactId>
@@ -156,6 +161,16 @@
                     <groupId>org.apache.ivy</groupId>
                     <artifactId>ivy</artifactId>
                 </exclusion>
+                <!-- Spark 3.3.2 includes self-conflicting versions of snappy -->
+                <exclusion>
+                    <groupId>org.xerial.snappy</groupId>
+                    <artifactId>snappy-java</artifactId>
+                </exclusion>
+                <!-- Excluding this log4j binding as it leads to NoSuchMethodErrors -->
+                <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-slf4j-impl</artifactId>
+                </exclusion>
             </exclusions>
         </dependency>
         <!-- resolve spark-gremlin conflicts -->
@@ -206,23 +221,23 @@
         <dependency>
             <groupId>org.scala-lang</groupId>
             <artifactId>scala-library</artifactId>
-            <version>2.12.10</version>
+            <version>2.12.15</version>
         </dependency>
-        <!-- use jackson 2.12.7 to fit better with spark where Scala module 2.12.3 requires Jackson Databind version >= 2.12.0 and < 2.13.0 -->
+        <!-- use jackson 2.13.5 to fit better with spark 2.3.3 where Scala module 2.13.4 requires Jackson Databind version >= 2.13.0 and < 2.14.0 -->
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-annotations</artifactId>
-            <version>2.12.7</version>
+            <version>2.13.5</version>
         </dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-core</artifactId>
-            <version>2.12.7</version>
+            <version>2.13.5</version>
         </dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-databind</artifactId>
-            <version>2.12.7</version>
+            <version>2.13.5</version>
         </dependency>
         <!-- TEST -->
         <dependency>
@@ -260,6 +275,12 @@
             <artifactId>logback-classic</artifactId>
             <scope>test</scope>
         </dependency>
+        <!-- Spark contains conflicting versions of snappy so it is excluded above. Include the newer version here. -->
+        <dependency>
+            <groupId>org.xerial.snappy</groupId>
+            <artifactId>snappy-java</artifactId>
+            <version>1.1.8.4</version>
+        </dependency>
     </dependencies>
     <build>
         <directory>${basedir}/target</directory>
@@ -331,13 +352,6 @@
                             <Gremlin-Plugin-Dependencies>
                                 org.apache.hadoop:hadoop-client:${hadoop.version};org.apache.hadoop:hadoop-yarn-server-web-proxy:${hadoop.version};org.apache.spark:spark-yarn_2.12:${spark.version}
                             </Gremlin-Plugin-Dependencies>
-                            <!-- initialization failures for using jackson after 2.12.* and hadoop pulls these in -->
-                            <Gremlin-Plugin-Paths>
-                                jackson-annotations-2.13.2.jar=;jackson-databind-2.13.2.2.jar=;jackson-core-2.13.2.jar=
-                            </Gremlin-Plugin-Paths>
-                            <Gremlin-Lib-Paths>
-                                jackson-annotations-2.13.2.jar=;jackson-databind-2.13.2.2.jar=;jackson-core-2.13.2.jar=
-                            </Gremlin-Lib-Paths>
                         </manifestEntries>
                     </archive>
                 </configuration>
diff --git a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/SparkGraphFeatureIntegrateTest.java b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/SparkGraphFeatureIntegrateTest.java
index a2b1a3d..d3f9bed 100644
--- a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/SparkGraphFeatureIntegrateTest.java
+++ b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/SparkGraphFeatureIntegrateTest.java
@@ -57,7 +57,7 @@
 
 @RunWith(Cucumber.class)
 @CucumberOptions(
-        tags = "not @RemoteOnly and not @StepDrop and not @StepV and not @StepIndex and not @StepInject and " +
+        tags = "not @RemoteOnly and not @StepDrop and not @StepV and not @StepE and not @StepIndex and not @StepInject and " +
                "not @GraphComputerVerificationOneBulk and not @GraphComputerVerificationStrategyNotSupported and " +
                "not @GraphComputerVerificationMidVNotSupported and not @GraphComputerVerificationElementSupported and " +
                "not @GraphComputerVerificationInjectionNotSupported and " +
diff --git a/sparql-gremlin/pom.xml b/sparql-gremlin/pom.xml
index 99e2bf4..24a572c 100644
--- a/sparql-gremlin/pom.xml
+++ b/sparql-gremlin/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>tinkerpop</artifactId>
         <groupId>org.apache.tinkerpop</groupId>
-        <version>3.6.5-SNAPSHOT</version>
+        <version>3.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>sparql-gremlin</artifactId>
     <name>Apache TinkerPop :: SPARQL Gremlin</name>
diff --git a/tinkergraph-gremlin/pom.xml b/tinkergraph-gremlin/pom.xml
index 9251b9e..aa37252 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.6.5-SNAPSHOT</version>
+        <version>3.7.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/structure/TinkerGraph.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java
index 3a4651e..0a598de 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
@@ -103,9 +103,9 @@
     protected TinkerIndex<TinkerVertex> vertexIndex = null;
     protected TinkerIndex<TinkerEdge> edgeIndex = null;
 
-    protected final IdManager<?> vertexIdManager;
-    protected final IdManager<?> edgeIdManager;
-    protected final IdManager<?> vertexPropertyIdManager;
+    protected IdManager<?> vertexIdManager;
+    protected IdManager<?> edgeIdManager;
+    protected IdManager<?> vertexPropertyIdManager;
     protected final VertexProperty.Cardinality defaultVertexPropertyCardinality;
     protected final boolean allowNullPropertyValues;
 
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphWorld.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphWorld.java
index 5810b99..ee915ac 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphWorld.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/TinkerGraphWorld.java
@@ -116,6 +116,7 @@
                 "@StepDrop",
                 "@StepInject",
                 "@StepV",
+                "@StepE",
                 "@GraphComputerVerificationOneBulk",
                 "@GraphComputerVerificationStrategyNotSupported",
                 "@GraphComputerVerificationMidVNotSupported",
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV1d0Test.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV1d0Test.java
index fff3be6..3413cea 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV1d0Test.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV1d0Test.java
@@ -27,12 +27,12 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.junit.MockitoJUnitRunner;
 
 import java.util.Arrays;
 
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV2d0Test.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV2d0Test.java
index 7551591..79c5070 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV2d0Test.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV2d0Test.java
@@ -27,12 +27,12 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.junit.MockitoJUnitRunner;
 
 import java.util.Arrays;
 
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV3d0Test.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV3d0Test.java
index 2b18c3b..55472df 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV3d0Test.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV3d0Test.java
@@ -27,12 +27,12 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.junit.MockitoJUnitRunner;
 
 import java.util.Arrays;
 
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;