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

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

commit 2e711729bdbcc843139fdc5c3fb585f6f9dcc6dc
Author: Cole Greer <[email protected]>
AuthorDate: Wed Jun 10 21:22:22 2026 -0700

    Address PDT PR review: SPI auto-wiring, API renames, test relocation
    
    - Auto-wire an SPI-discovered ProviderDefinedTypeRegistry by default on the
      Java driver path so registered adapters hydrate/dehydrate with zero 
config:
      the default GraphBinaryMessageSerializerV4 and DriverRemoteConnection now 
use
      ProviderDefinedTypeRegistry.create(). setPdtRegistry and explicit 
serializer
      registries remain as overrides.
    - Rename the registry factory build() -> create() across Java, Python, and
      .NET (Go's NewPDTRegistry and JS's constructor are already idiomatic). The
      old name misleadingly implied the Builder pattern.
    - Rename the PDT field map terminology properties -> fields across all GLVs
      (getFields/Fields, toFields/fromFields) to match the @ProviderDefined
      annotation and the GraphSON wire format, and disambiguate from Element
      properties. Wire formats and binary layouts are unchanged.
    - Document that equals()/hashCode() intentionally exclude the transient
      hydrated field.
    - Move the PDT GraphBinary serializer tests from gremlin-core to 
gremlin-util
      and delete the bespoke HeapBuffer, reusing the netty-backed buffer 
pattern.
    - Update provider and reference docs for the renames.
    
    Assisted-by: Kiro:claude-opus-4.8
---
 docs/src/dev/provider/index.asciidoc               |  18 +-
 docs/src/reference/gremlin-variants.asciidoc       |  34 +--
 .../gremlin/process/traversal/GremlinLang.java     |   4 +-
 .../types/ProviderDefinedTypeSerializer.java       |  12 +-
 .../io/graphson/PdtGraphSONSerializersV4.java      |   2 +-
 .../structure/io/pdt/ProviderDefinedType.java      |  31 +--
 .../io/pdt/ProviderDefinedTypeAdapter.java         |   6 +-
 .../io/pdt/ProviderDefinedTypeRegistry.java        |  16 +-
 .../grammar/GeneralLiteralVisitorTest.java         |   6 +-
 .../gremlin/process/traversal/GremlinLangTest.java |   4 +-
 .../gremlin/structure/io/binary/HeapBuffer.java    | 230 ---------------------
 .../io/graphson/PdtGraphSONSerializersV4Test.java  |  30 +--
 .../io/pdt/ProviderDefinedTypeRegistryTest.java    |  24 +--
 .../structure/io/pdt/ProviderDefinedTypeTest.java  |  46 ++---
 .../Gremlin.Net/Process/Traversal/GremlinLang.cs   |   8 +-
 .../GraphBinary4/Types/CompositePDTSerializer.cs   |  10 +-
 .../Structure/IProviderDefinedTypeAdapter.cs       |   8 +-
 .../Structure/ProviderDefinedAttribute.cs          |   2 +-
 .../Gremlin.Net/Structure/ProviderDefinedType.cs   |  20 +-
 .../Structure/ProviderDefinedTypeRegistry.cs       |  18 +-
 .../Driver/DriverRemoteConnectionTests.cs          |  12 +-
 .../Driver/GremlinClientTests.cs                   |  26 +--
 .../Process/Traversal/GremlinLangTests.cs          |   6 +-
 .../IO/GraphBinary4/ProviderDefinedTypeTests.cs    |   6 +-
 .../Structure/ProviderDefinedTypeRegistryTests.cs  |  30 +--
 .../driver/remote/DriverRemoteConnection.java      |   5 +-
 gremlin-go/driver/client_test.go                   |  24 +--
 gremlin-go/driver/graphBinaryDeserializer.go       |   4 +-
 gremlin-go/driver/graphBinarySerializer_test.go    |  28 +--
 gremlin-go/driver/gremlinlang.go                   |   8 +-
 gremlin-go/driver/gremlinlang_test.go              |  14 +-
 gremlin-go/driver/pdtRegistry.go                   |  22 +-
 gremlin-go/driver/pdtRegistry_test.go              |  12 +-
 gremlin-go/driver/providerDefinedType.go           |  14 +-
 gremlin-go/driver/providerDefinedType_test.go      |   4 +-
 gremlin-go/driver/traversal_test.go                |   6 +-
 .../python/gremlin_python/process/traversal.py     |   2 +-
 .../main/python/gremlin_python/structure/graph.py  |  26 +--
 .../gremlin_python/structure/io/graphbinaryV4.py   |   8 +-
 .../tests/unit/structure/io/test_graphbinaryV4.py  |  12 +-
 .../structure/io/test_provider_defined_type.py     |   6 +-
 .../gremlin/server/GremlinDriverIntegrateTest.java |  12 +-
 .../GremlinServerSerializationIntegrateTest.java   |  22 +-
 .../util/ser/GraphBinaryMessageSerializerV4.java   |  13 +-
 .../binary/GraphBinaryPdtSpiAutoWiringTest.java    | 134 ++++++++++++
 .../util/ser}/binary/GraphBinaryWriterPdtTest.java |  18 +-
 .../gremlin/util/ser/binary/TestPointAdapter.java  |  63 ++++++
 .../types/ProviderDefinedTypeSerializerTest.java   |  23 ++-
 ...lin.structure.io.pdt.ProviderDefinedTypeAdapter |   1 +
 49 files changed, 537 insertions(+), 553 deletions(-)

diff --git a/docs/src/dev/provider/index.asciidoc 
b/docs/src/dev/provider/index.asciidoc
index 511e6a67cd..59c1b32ca1 100644
--- a/docs/src/dev/provider/index.asciidoc
+++ b/docs/src/dev/provider/index.asciidoc
@@ -1426,13 +1426,13 @@ public class ColorAdapter implements 
ProviderDefinedTypeAdapter<java.awt.Color>
     public Class<java.awt.Color> targetClass() { return java.awt.Color.class; }
 
     @Override
-    public Map<String, Object> toProperties(java.awt.Color color) {
+    public Map<String, Object> toFields(java.awt.Color color) {
         return Map.of("r", color.getRed(), "g", color.getGreen(),
                       "b", color.getBlue(), "a", color.getAlpha());
     }
 
     @Override
-    public java.awt.Color fromProperties(Map<String, Object> fields) {
+    public java.awt.Color fromFields(Map<String, Object> fields) {
         return new java.awt.Color((int) fields.get("r"), (int) fields.get("g"),
                                   (int) fields.get("b"), (int) 
fields.get("a"));
     }
@@ -1461,12 +1461,12 @@ annotation to derive the type name and field mapping 
automatically:
 
 [source,java]
 ----
-ProviderDefinedTypeRegistry registry = ProviderDefinedTypeRegistry.build();
+ProviderDefinedTypeRegistry registry = ProviderDefinedTypeRegistry.create();
 registry.register(Point.class, Address.class, Person.class);
 ----
 
 Adapter types (for classes you don't own) are discovered automatically via 
`ServiceLoader` when using
-`ProviderDefinedTypeRegistry.build()`. Register them by adding a file at:
+`ProviderDefinedTypeRegistry.create()`. Register them by adding a file at:
 
 ----
 
META-INF/services/org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter
@@ -1485,9 +1485,9 @@ definition time (import time), so any annotated type 
round-trips without any add
 
 ===== .NET
 
-`[ProviderDefined]`-annotated types are discovered automatically. Calling 
`ProviderDefinedTypeRegistry.Build()`
+`[ProviderDefined]`-annotated types are discovered automatically. Calling 
`ProviderDefinedTypeRegistry.Create()`
 scans all loaded assemblies for `[ProviderDefined]`-annotated types and 
registers them for hydration. No extra
-configuration is needed — providers simply annotate their types and users call 
`Build()` to create the registry.
+configuration is needed — providers simply annotate their types and users call 
`Create()` to create the registry.
 
 ===== JavaScript
 
@@ -1524,7 +1524,7 @@ the registry is populated:
 // In the provider's client library
 public class MyGraphTypeRegistry {
     public static ProviderDefinedTypeRegistry build() {
-        ProviderDefinedTypeRegistry registry = 
ProviderDefinedTypeRegistry.build(); // discovers ServiceLoader adapters
+        ProviderDefinedTypeRegistry registry = 
ProviderDefinedTypeRegistry.create(); // discovers ServiceLoader adapters
         registry.register(Point.class, Address.class, Person.class);           
    // registers annotated types
         return registry;
     }
@@ -1549,7 +1549,7 @@ each language driver.
 ==== JPMS Considerations
 
 Annotation-based PDT hydration uses reflection internally — specifically 
`Constructor.setAccessible(true)` and
-`Field.set()` on the provider's annotated class (see 
`AnnotatedTypeAdapter.fromProperties` in
+`Field.set()` on the provider's annotated class (see 
`AnnotatedTypeAdapter.fromFields` in
 `ProviderDefinedTypeRegistry`). Under the Java Platform Module System (JPMS), 
this means the provider's module must
 `opens` its PDT package to `org.apache.tinkerpop.gremlin.core` (or to 
`ALL-UNNAMED` for classpath usage), otherwise
 the JVM will throw `InaccessibleObjectException` at hydration time.
@@ -1569,7 +1569,7 @@ Alternatively, providers that cannot modify their module 
descriptor can pass JVM
 ----
 
 NOTE: This only applies to annotation-based hydration. Providers using 
`ProviderDefinedTypeAdapter` with explicit
-`fromProperties` logic do not require reflective access and are unaffected by 
JPMS restrictions.
+`fromFields` logic do not require reflective access and are unaffected by JPMS 
restrictions.
 
 [[gremlin-plugins]]
 == Gremlin Plugins
diff --git a/docs/src/reference/gremlin-variants.asciidoc 
b/docs/src/reference/gremlin-variants.asciidoc
index 2583e93ebf..38c252a5b2 100644
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@ -627,8 +627,8 @@ Consult your graph provider's documentation for the list of 
PDTs they support.
 ----
 results, err := g.V().Has("location").Values("location").ToList()
 pdt := results[0].GetInterface().(*gremlingo.ProviderDefinedType)
-fmt.Println(pdt.Name)       // "x:Point"
-fmt.Println(pdt.Properties) // map[x:1.0 y:2.0]
+fmt.Println(pdt.Name)   // "x:Point"
+fmt.Println(pdt.Fields) // map[x:1.0 y:2.0]
 ----
 
 Working with raw `*ProviderDefinedType` values is always available. Using a 
`PDTRegistry` is an optional
@@ -1560,7 +1560,7 @@ Receiving a raw PDT:
 ----
 ProviderDefinedType pdt = (ProviderDefinedType) 
g.V().has("location").values("location").next();
 String typeName = pdt.getName();                   // "x:Point"
-Map<String, Object> props = pdt.getProperties();   // {x: 1.0, y: 2.0}
+Map<String, Object> fields = pdt.getFields();      // {x: 1.0, y: 2.0}
 ----
 
 Working with raw `ProviderDefinedType` objects is always available. The 
following two approaches are optional
@@ -1571,8 +1571,8 @@ Using a `ProviderDefinedTypeRegistry` for hydration and 
dehydration:
 public class PointAdapter implements ProviderDefinedTypeAdapter<Point> {
     @Override public String typeName() { return "x:Point"; }
     @Override public Class<Point> targetClass() { return Point.class; }
-    @Override public Map<String, Object> toProperties(Point p) { return 
Map.of("x", p.getX(), "y", p.getY()); }
-    @Override public Point fromProperties(Map<String, Object> m) { return new 
Point((double) m.get("x"), (double) m.get("y")); }
+    @Override public Map<String, Object> toFields(Point p) { return 
Map.of("x", p.getX(), "y", p.getY()); }
+    @Override public Point fromFields(Map<String, Object> m) { return new 
Point((double) m.get("x"), (double) m.get("y")); }
 }
 ----
 
@@ -2224,8 +2224,8 @@ Receiving a raw PDT:
 ----
 const results = await g.V().has('location').values('location').toList();
 const pdt = results[0];
-console.log(pdt.name);       // "x:Point"
-console.log(pdt.properties); // { x: 1.0, y: 2.0 }
+console.log(pdt.name);   // "x:Point"
+console.log(pdt.fields); // { x: 1.0, y: 2.0 }
 ----
 
 Working with raw `ProviderDefinedType` objects is always available. Using a 
`ProviderDefinedTypeRegistry` is an
@@ -2707,8 +2707,8 @@ Receiving a raw PDT:
 [source,csharp]
 ----
 var pdt = (ProviderDefinedType) 
g.V().Has("location").Values<object>("location").Next();
-Console.WriteLine(pdt.Name);       // "x:Point"
-Console.WriteLine(pdt.Properties); // { x: 1.0, y: 2.0 }
+Console.WriteLine(pdt.Name);   // "x:Point"
+Console.WriteLine(pdt.Fields); // { x: 1.0, y: 2.0 }
 ----
 
 Working with raw `ProviderDefinedType` objects is always available. The 
following two approaches are optional
@@ -2722,10 +2722,10 @@ public class PointAdapter : 
IProviderDefinedTypeAdapter<Point>
 {
     public string TypeName => "x:Point";
 
-    public Point FromProperties(IReadOnlyDictionary<string, object?> 
properties) =>
-        new Point((double)properties["x"], (double)properties["y"]);
+    public Point FromFields(IReadOnlyDictionary<string, object?> fields) =>
+        new Point((double)fields["x"], (double)fields["y"]);
 
-    public IReadOnlyDictionary<string, object?> ToProperties(Point value) =>
+    public IReadOnlyDictionary<string, object?> ToFields(Point value) =>
         new Dictionary<string, object?> { ["x"] = value.X, ["y"] = value.Y };
 }
 
@@ -2735,7 +2735,7 @@ registry.Register(new PointAdapter());
 using var client = new GremlinClient(new GremlinServer("localhost", 8182), 
pdtRegistry: registry);
 ----
 
-The `ProviderDefinedTypeRegistry.Build()` method scans loaded assemblies for 
`IProviderDefinedTypeAdapter<T>`
+The `ProviderDefinedTypeRegistry.Create()` method scans loaded assemblies for 
`IProviderDefinedTypeAdapter<T>`
 implementations and registers them automatically.
 
 For simpler cases where you own the type, annotate it directly to avoid 
writing an adapter:
@@ -3345,8 +3345,8 @@ Receiving a raw PDT:
 [source,python]
 ----
 pdt = g.V().has('location').values('location').next()
-print(pdt.name)       # "x:Point"
-print(pdt.properties) # {'x': 1.0, 'y': 2.0}
+print(pdt.name)   # "x:Point"
+print(pdt.fields) # {'x': 1.0, 'y': 2.0}
 ----
 
 Working with raw `ProviderDefinedType` objects is always available. The 
following two approaches are optional
@@ -3360,7 +3360,7 @@ from gremlin_python.structure.graph import 
ProviderDefinedTypeRegistry
 
 registry = ProviderDefinedTypeRegistry()
 registry.register('x:Point',
-    deserialize_fn=lambda props: Point(props['x'], props['y']),
+    deserialize_fn=lambda fields: Point(fields['x'], fields['y']),
     serialize_fn=lambda p: {'x': p.x, 'y': p.y},
     target_class=Point)
 
@@ -3368,7 +3368,7 @@ g = 
traversal().with_(DriverRemoteConnection('http://localhost:8182/gremlin', 'g
     pdt_registry=registry))
 ----
 
-The `ProviderDefinedTypeRegistry.build()` class method discovers adapters via 
`entry_points` in `pyproject.toml`
+The `ProviderDefinedTypeRegistry.create()` class method discovers adapters via 
`entry_points` in `pyproject.toml`
 under the `tinkerpop.pdt` group.
 
 For simpler cases where you own the type, the `@provider_defined` decorator 
enables automatic round-trip conversion
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java
index 3e651be971..1edc6217d7 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java
@@ -191,7 +191,7 @@ public class GremlinLang implements Cloneable, Serializable 
{
 
         if (arg instanceof ProviderDefinedType) {
             final ProviderDefinedType pdt = (ProviderDefinedType) arg;
-            return "PDT(" + argAsString(pdt.getName()) + "," + 
asString((Map<?, ?>) pdt.getProperties()) + ")";
+            return "PDT(" + argAsString(pdt.getName()) + "," + 
asString((Map<?, ?>) pdt.getFields()) + ")";
         }
 
         if (arg instanceof Enum) {
@@ -273,7 +273,7 @@ public class GremlinLang implements Cloneable, Serializable 
{
             final Optional<ProviderDefinedTypeAdapter<?>> adapter = 
pdtRegistry.getAdapterByClass(arg.getClass());
             if (adapter.isPresent()) {
                 @SuppressWarnings("unchecked")
-                final Map<String, Object> props = 
((ProviderDefinedTypeAdapter) adapter.get()).toProperties(arg);
+                final Map<String, Object> props = 
((ProviderDefinedTypeAdapter) adapter.get()).toFields(arg);
                 return argAsString(new 
ProviderDefinedType(adapter.get().typeName(), props));
             }
         }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ProviderDefinedTypeSerializer.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ProviderDefinedTypeSerializer.java
index d45b4cf2a9..a833d2d46a 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ProviderDefinedTypeSerializer.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ProviderDefinedTypeSerializer.java
@@ -38,19 +38,19 @@ public class ProviderDefinedTypeSerializer extends 
SimpleTypeSerializer<Provider
         final String name = context.read(buffer);
         if (name == null || name.isEmpty())
             throw new IOException("ProviderDefinedType name cannot be null or 
empty");
-        final Map<?, ?> properties = context.read(buffer);
-        for (final Object key : properties.keySet()) {
+        final Map<?, ?> fields = context.read(buffer);
+        for (final Object key : fields.keySet()) {
             if (!(key instanceof String))
-                throw new IOException("ProviderDefinedType properties map must 
have String keys, found: " + key.getClass().getName());
+                throw new IOException("ProviderDefinedType fields map must 
have String keys, found: " + key.getClass().getName());
         }
         @SuppressWarnings("unchecked")
-        final Map<String, Object> typedProperties = (Map<String, Object>) 
(Map<?, ?>) properties;
-        return new ProviderDefinedType(name, typedProperties);
+        final Map<String, Object> typedFields = (Map<String, Object>) (Map<?, 
?>) fields;
+        return new ProviderDefinedType(name, typedFields);
     }
 
     @Override
     protected void writeValue(final ProviderDefinedType value, final Buffer 
buffer, final GraphBinaryWriter context) throws IOException {
         context.write(value.getName(), buffer);
-        context.write(value.getProperties(), buffer);
+        context.write(value.getFields(), buffer);
     }
 }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/PdtGraphSONSerializersV4.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/PdtGraphSONSerializersV4.java
index fb4cd848a3..de116f54aa 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/PdtGraphSONSerializersV4.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/PdtGraphSONSerializersV4.java
@@ -53,7 +53,7 @@ final class PdtGraphSONSerializersV4 {
             jsonGenerator.writeStringField("type", pdt.getName());
             jsonGenerator.writeFieldName("fields");
             jsonGenerator.writeStartObject();
-            for (final Map.Entry<String, Object> entry : 
pdt.getProperties().entrySet()) {
+            for (final Map.Entry<String, Object> entry : 
pdt.getFields().entrySet()) {
                 jsonGenerator.writeFieldName(entry.getKey());
                 jsonGenerator.writeObject(entry.getValue());
             }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedType.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedType.java
index 3a67209db9..391d06fd94 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedType.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedType.java
@@ -31,23 +31,23 @@ import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
- * An immutable representation of a provider-defined type consisting of a name 
and a map of properties.
+ * An immutable representation of a provider-defined type consisting of a name 
and a map of fields.
  */
 public final class ProviderDefinedType {
 
     private static final ConcurrentHashMap<Class<?>, FieldCache> FIELD_CACHE = 
new ConcurrentHashMap<>();
 
     private final String name;
-    private final Map<String, Object> properties;
+    private final Map<String, Object> fields;
     private Object hydrated;
 
-    public ProviderDefinedType(final String name, final Map<String, Object> 
properties) {
+    public ProviderDefinedType(final String name, final Map<String, Object> 
fields) {
         if (name == null || name.isEmpty())
             throw new IllegalArgumentException("name cannot be null or empty");
-        if (properties == null)
-            throw new IllegalArgumentException("properties cannot be null");
+        if (fields == null)
+            throw new IllegalArgumentException("fields cannot be null");
         this.name = name;
-        this.properties = Collections.unmodifiableMap(new 
LinkedHashMap<>(properties));
+        this.fields = Collections.unmodifiableMap(new LinkedHashMap<>(fields));
     }
 
     /**
@@ -139,15 +139,15 @@ public final class ProviderDefinedType {
         return name;
     }
 
-    public Map<String, Object> getProperties() {
-        return properties;
+    public Map<String, Object> getFields() {
+        return fields;
     }
 
     /**
      * Returns a copy of this PDT with the hydrated object attached.
      */
     public ProviderDefinedType withHydrated(final Object hydrated) {
-        final ProviderDefinedType copy = new ProviderDefinedType(this.name, 
this.properties);
+        final ProviderDefinedType copy = new ProviderDefinedType(this.name, 
this.fields);
         copy.hydrated = hydrated;
         return copy;
     }
@@ -159,21 +159,28 @@ public final class ProviderDefinedType {
         return hydrated;
     }
 
+    /**
+     * Equality is based solely on {@code name} and {@code fields} (the 
serialized wire form).
+     * The {@code hydrated} field is intentionally excluded — it is a 
transient, derived view
+     * cached by the deserializer via {@link #withHydrated(Object)} and is not 
part of the
+     * type's logical identity.
+     */
     @Override
     public boolean equals(final Object o) {
         if (this == o) return true;
         if (!(o instanceof ProviderDefinedType)) return false;
         final ProviderDefinedType that = (ProviderDefinedType) o;
-        return name.equals(that.name) && properties.equals(that.properties);
+        return name.equals(that.name) && fields.equals(that.fields);
     }
 
+    /** See {@link #equals(Object)} for rationale on field inclusion. */
     @Override
     public int hashCode() {
-        return Objects.hash(name, properties);
+        return Objects.hash(name, fields);
     }
 
     @Override
     public String toString() {
-        return "pdt[" + name + "]" + properties;
+        return "pdt[" + name + "]" + fields;
     }
 }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeAdapter.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeAdapter.java
index 86880a0584..701fba0d49 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeAdapter.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeAdapter.java
@@ -21,11 +21,11 @@ package org.apache.tinkerpop.gremlin.structure.io.pdt;
 import java.util.Map;
 
 /**
- * Adapter for converting between a typed object and a {@link 
ProviderDefinedType} property map.
+ * Adapter for converting between a typed object and a {@link 
ProviderDefinedType} field map.
  */
 public interface ProviderDefinedTypeAdapter<T> {
     String typeName();
     Class<T> targetClass();
-    Map<String, Object> toProperties(T obj);
-    T fromProperties(Map<String, Object> properties);
+    Map<String, Object> toFields(T obj);
+    T fromFields(Map<String, Object> fields);
 }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeRegistry.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeRegistry.java
index 10d63bc92f..015b2ffee0 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeRegistry.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeRegistry.java
@@ -49,7 +49,7 @@ public final class ProviderDefinedTypeRegistry {
      * Creates a registry populated via {@link ServiceLoader} discovery.
      */
     @SuppressWarnings("rawtypes")
-    public static ProviderDefinedTypeRegistry build() {
+    public static ProviderDefinedTypeRegistry create() {
         final ProviderDefinedTypeRegistry registry = new 
ProviderDefinedTypeRegistry();
         for (final ProviderDefinedTypeAdapter adapter : 
ServiceLoader.load(ProviderDefinedTypeAdapter.class)) {
             registry.register(adapter);
@@ -101,14 +101,14 @@ public final class ProviderDefinedTypeRegistry {
         if (adapter == null)
             return pdt;
 
-        // recursively hydrate nested PDTs in the properties map
+        // recursively hydrate nested PDTs in the fields map
         final Map<String, Object> hydrated = new LinkedHashMap<>();
-        for (final Map.Entry<String, Object> entry : 
pdt.getProperties().entrySet()) {
+        for (final Map.Entry<String, Object> entry : 
pdt.getFields().entrySet()) {
             hydrated.put(entry.getKey(), hydrateValue(entry.getValue()));
         }
 
         try {
-            return adapter.fromProperties(hydrated);
+            return adapter.fromFields(hydrated);
         } catch (final Exception e) {
             logger.warn("Failed to hydrate ProviderDefinedType '{}', returning 
raw PDT: {}",
                     pdt.getName(), e.getMessage());
@@ -176,18 +176,18 @@ public final class ProviderDefinedTypeRegistry {
         @Override public Class<T> targetClass() { return targetClass; }
 
         @Override
-        public Map<String, Object> toProperties(final T obj) {
-            return ProviderDefinedType.from(obj).getProperties();
+        public Map<String, Object> toFields(final T obj) {
+            return ProviderDefinedType.from(obj).getFields();
         }
 
         @Override
-        public T fromProperties(final Map<String, Object> properties) {
+        public T fromFields(final Map<String, Object> fieldMap) {
             try {
                 final java.lang.reflect.Constructor<T> ctor = 
targetClass.getDeclaredConstructor();
                 ctor.setAccessible(true);
                 final T obj = ctor.newInstance();
                 for (final Field field : fields) {
-                    final Object value = properties.get(field.getName());
+                    final Object value = fieldMap.get(field.getName());
                     if (value != null)
                         field.set(obj, coerce(value, field.getType()));
                 }
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
index 953565679b..67bf4ffef0 100644
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
@@ -1061,8 +1061,8 @@ public class GeneralLiteralVisitorTest {
             assertThat(result, instanceOf(ProviderDefinedType.class));
             final ProviderDefinedType pdt = (ProviderDefinedType) result;
             assertEquals("MyType", pdt.getName());
-            assertEquals(1, pdt.getProperties().get("x"));
-            assertEquals("hello", pdt.getProperties().get("y"));
+            assertEquals(1, pdt.getFields().get("x"));
+            assertEquals("hello", pdt.getFields().get("y"));
         }
 
         @Test
@@ -1074,7 +1074,7 @@ public class GeneralLiteralVisitorTest {
             assertThat(result, instanceOf(ProviderDefinedType.class));
             final ProviderDefinedType pdt = (ProviderDefinedType) result;
             assertEquals("Empty", pdt.getName());
-            assertTrue(pdt.getProperties().isEmpty());
+            assertTrue(pdt.getFields().isEmpty());
         }
 
         @Test
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLangTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLangTest.java
index 24988ed084..1164a5610d 100644
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLangTest.java
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLangTest.java
@@ -473,10 +473,10 @@ public class GremlinLangTest {
             registry.register(new ProviderDefinedTypeAdapter<DualType>() {
                 @Override public String typeName() { return "AdapterName"; }
                 @Override public Class<DualType> targetClass() { return 
DualType.class; }
-                @Override public Map<String, Object> toProperties(final 
DualType obj) {
+                @Override public Map<String, Object> toFields(final DualType 
obj) {
                     return Collections.singletonMap("v", obj.value);
                 }
-                @Override public DualType fromProperties(final Map<String, 
Object> properties) {
+                @Override public DualType fromFields(final Map<String, Object> 
properties) {
                     return new DualType((int) properties.get("v"));
                 }
             });
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/binary/HeapBuffer.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/binary/HeapBuffer.java
deleted file mode 100644
index e7f090cd1b..0000000000
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/binary/HeapBuffer.java
+++ /dev/null
@@ -1,230 +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.structure.io.binary;
-
-import org.apache.tinkerpop.gremlin.structure.io.Buffer;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-
-/**
- * A simple heap-based {@link Buffer} implementation for unit testing in 
gremlin-core.
- */
-public class HeapBuffer implements Buffer {
-    private byte[] data;
-    private int readerIndex;
-    private int writerIndex;
-    private int markedWriterIndex;
-
-    public HeapBuffer(final int initialCapacity) {
-        this.data = new byte[initialCapacity];
-    }
-
-    public static HeapBuffer allocate(final int capacity) {
-        return new HeapBuffer(capacity);
-    }
-
-    private void ensureCapacity(final int needed) {
-        if (writerIndex + needed > data.length) {
-            data = Arrays.copyOf(data, Math.max(data.length * 2, writerIndex + 
needed));
-        }
-    }
-
-    @Override public int readableBytes() { return writerIndex - readerIndex; }
-    @Override public int readerIndex() { return readerIndex; }
-    @Override public Buffer readerIndex(final int readerIndex) { 
this.readerIndex = readerIndex; return this; }
-    @Override public int writerIndex() { return writerIndex; }
-    @Override public Buffer writerIndex(final int writerIndex) { 
this.writerIndex = writerIndex; return this; }
-    @Override public Buffer markWriterIndex() { this.markedWriterIndex = 
writerIndex; return this; }
-    @Override public Buffer resetWriterIndex() { this.writerIndex = 
markedWriterIndex; return this; }
-    @Override public int capacity() { return data.length; }
-    @Override public boolean isDirect() { return false; }
-
-    @Override
-    public boolean readBoolean() { return readByte() != 0; }
-
-    @Override
-    public byte readByte() { return data[readerIndex++]; }
-
-    @Override
-    public short readShort() {
-        short v = (short) ((data[readerIndex] & 0xFF) << 8 | (data[readerIndex 
+ 1] & 0xFF));
-        readerIndex += 2;
-        return v;
-    }
-
-    @Override
-    public int readInt() {
-        int v = (data[readerIndex] & 0xFF) << 24 | (data[readerIndex + 1] & 
0xFF) << 16 |
-                (data[readerIndex + 2] & 0xFF) << 8 | (data[readerIndex + 3] & 
0xFF);
-        readerIndex += 4;
-        return v;
-    }
-
-    @Override
-    public long readLong() {
-        long v = ((long)(data[readerIndex] & 0xFF) << 56) | 
((long)(data[readerIndex+1] & 0xFF) << 48) |
-                 ((long)(data[readerIndex+2] & 0xFF) << 40) | 
((long)(data[readerIndex+3] & 0xFF) << 32) |
-                 ((long)(data[readerIndex+4] & 0xFF) << 24) | 
((long)(data[readerIndex+5] & 0xFF) << 16) |
-                 ((long)(data[readerIndex+6] & 0xFF) << 8)  | 
((long)(data[readerIndex+7] & 0xFF));
-        readerIndex += 8;
-        return v;
-    }
-
-    @Override
-    public float readFloat() { return Float.intBitsToFloat(readInt()); }
-
-    @Override
-    public double readDouble() { return Double.longBitsToDouble(readLong()); }
-
-    @Override
-    public Buffer readBytes(final byte[] destination) {
-        System.arraycopy(data, readerIndex, destination, 0, 
destination.length);
-        readerIndex += destination.length;
-        return this;
-    }
-
-    @Override
-    public Buffer readBytes(final byte[] destination, final int dstIndex, 
final int length) {
-        System.arraycopy(data, readerIndex, destination, dstIndex, length);
-        readerIndex += length;
-        return this;
-    }
-
-    @Override
-    public Buffer readBytes(final ByteBuffer dst) {
-        int len = dst.remaining();
-        dst.put(data, readerIndex, len);
-        readerIndex += len;
-        return this;
-    }
-
-    @Override
-    public Buffer readBytes(final OutputStream out, final int length) throws 
IOException {
-        out.write(data, readerIndex, length);
-        readerIndex += length;
-        return this;
-    }
-
-    @Override
-    public Buffer writeBoolean(final boolean value) { return writeByte(value ? 
1 : 0); }
-
-    @Override
-    public Buffer writeByte(final int value) {
-        ensureCapacity(1);
-        data[writerIndex++] = (byte) value;
-        return this;
-    }
-
-    @Override
-    public Buffer writeShort(final int value) {
-        ensureCapacity(2);
-        data[writerIndex++] = (byte) (value >>> 8);
-        data[writerIndex++] = (byte) value;
-        return this;
-    }
-
-    @Override
-    public Buffer writeInt(final int value) {
-        ensureCapacity(4);
-        data[writerIndex++] = (byte) (value >>> 24);
-        data[writerIndex++] = (byte) (value >>> 16);
-        data[writerIndex++] = (byte) (value >>> 8);
-        data[writerIndex++] = (byte) value;
-        return this;
-    }
-
-    @Override
-    public Buffer writeLong(final long value) {
-        ensureCapacity(8);
-        data[writerIndex++] = (byte) (value >>> 56);
-        data[writerIndex++] = (byte) (value >>> 48);
-        data[writerIndex++] = (byte) (value >>> 40);
-        data[writerIndex++] = (byte) (value >>> 32);
-        data[writerIndex++] = (byte) (value >>> 24);
-        data[writerIndex++] = (byte) (value >>> 16);
-        data[writerIndex++] = (byte) (value >>> 8);
-        data[writerIndex++] = (byte) value;
-        return this;
-    }
-
-    @Override
-    public Buffer writeFloat(final float value) { return 
writeInt(Float.floatToIntBits(value)); }
-
-    @Override
-    public Buffer writeDouble(final double value) { return 
writeLong(Double.doubleToLongBits(value)); }
-
-    @Override
-    public Buffer writeBytes(final byte[] src) {
-        ensureCapacity(src.length);
-        System.arraycopy(src, 0, data, writerIndex, src.length);
-        writerIndex += src.length;
-        return this;
-    }
-
-    @Override
-    public Buffer writeBytes(final ByteBuffer src) {
-        int len = src.remaining();
-        ensureCapacity(len);
-        src.get(data, writerIndex, len);
-        writerIndex += len;
-        return this;
-    }
-
-    @Override
-    public Buffer writeBytes(final byte[] src, final int srcIndex, final int 
length) {
-        ensureCapacity(length);
-        System.arraycopy(src, srcIndex, data, writerIndex, length);
-        writerIndex += length;
-        return this;
-    }
-
-    @Override public boolean release() { return true; }
-    @Override public Buffer retain() { return this; }
-    @Override public int referenceCount() { return 1; }
-    @Override public int nioBufferCount() { return 1; }
-
-    @Override
-    public ByteBuffer[] nioBuffers() {
-        return new ByteBuffer[] { nioBuffer() };
-    }
-
-    @Override
-    public ByteBuffer[] nioBuffers(final int index, final int length) {
-        return new ByteBuffer[] { nioBuffer(index, length) };
-    }
-
-    @Override
-    public ByteBuffer nioBuffer() {
-        return ByteBuffer.wrap(data, readerIndex, readableBytes()).slice();
-    }
-
-    @Override
-    public ByteBuffer nioBuffer(final int index, final int length) {
-        return ByteBuffer.wrap(data, index, length).slice();
-    }
-
-    @Override
-    public Buffer getBytes(final int index, final byte[] dst) {
-        System.arraycopy(data, index, dst, 0, dst.length);
-        return this;
-    }
-}
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/PdtGraphSONSerializersV4Test.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/PdtGraphSONSerializersV4Test.java
index 67786dbcd8..1b54c39b39 100644
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/PdtGraphSONSerializersV4Test.java
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/PdtGraphSONSerializersV4Test.java
@@ -80,9 +80,9 @@ public class PdtGraphSONSerializersV4Test extends 
AbstractGraphSONTest {
         final ProviderDefinedType pdt = mapper.readValue(json, 
ProviderDefinedType.class);
 
         assertEquals("Point", pdt.getName());
-        assertEquals(2, pdt.getProperties().size());
-        assertEquals(1, pdt.getProperties().get("x"));
-        assertEquals(2, pdt.getProperties().get("y"));
+        assertEquals(2, pdt.getFields().size());
+        assertEquals(1, pdt.getFields().get("x"));
+        assertEquals(2, pdt.getFields().get("y"));
     }
 
     @Test
@@ -95,7 +95,7 @@ public class PdtGraphSONSerializersV4Test extends 
AbstractGraphSONTest {
         final ProviderDefinedType result = serializeDeserialize(mapper, 
original, ProviderDefinedType.class);
 
         assertEquals(original.getName(), result.getName());
-        assertEquals(original.getProperties(), result.getProperties());
+        assertEquals(original.getFields(), result.getFields());
     }
 
     @Test
@@ -122,11 +122,11 @@ public class PdtGraphSONSerializersV4Test extends 
AbstractGraphSONTest {
         // round-trip nested
         final ProviderDefinedType result = serializeDeserialize(mapper, outer, 
ProviderDefinedType.class);
         assertEquals("NamedPoint", result.getName());
-        assertTrue(result.getProperties().get("location") instanceof 
ProviderDefinedType);
-        final ProviderDefinedType nestedResult = (ProviderDefinedType) 
result.getProperties().get("location");
+        assertTrue(result.getFields().get("location") instanceof 
ProviderDefinedType);
+        final ProviderDefinedType nestedResult = (ProviderDefinedType) 
result.getFields().get("location");
         assertEquals("Point", nestedResult.getName());
-        assertEquals(10, nestedResult.getProperties().get("x"));
-        assertEquals(20, nestedResult.getProperties().get("y"));
+        assertEquals(10, nestedResult.getFields().get("x"));
+        assertEquals(20, nestedResult.getFields().get("y"));
     }
 
     @Test
@@ -139,9 +139,9 @@ public class PdtGraphSONSerializersV4Test extends 
AbstractGraphSONTest {
         final ProviderDefinedType result = serializeDeserialize(mapper, pdt, 
ProviderDefinedType.class);
 
         assertEquals("NullableType", result.getName());
-        assertEquals("test", result.getProperties().get("name"));
-        assertNull(result.getProperties().get("value"));
-        assertTrue(result.getProperties().containsKey("value"));
+        assertEquals("test", result.getFields().get("name"));
+        assertNull(result.getFields().get("value"));
+        assertTrue(result.getFields().containsKey("value"));
     }
 
     // --- Hydration tests ---
@@ -155,13 +155,13 @@ public class PdtGraphSONSerializersV4Test extends 
AbstractGraphSONTest {
     static class PointAdapter implements ProviderDefinedTypeAdapter<Point> {
         @Override public String typeName() { return "Point"; }
         @Override public Class<Point> targetClass() { return Point.class; }
-        @Override public Map<String, Object> toProperties(Point obj) {
+        @Override public Map<String, Object> toFields(Point obj) {
             final Map<String, Object> m = new HashMap<>();
             m.put("x", obj.x);
             m.put("y", obj.y);
             return m;
         }
-        @Override public Point fromProperties(Map<String, Object> properties) {
+        @Override public Point fromFields(Map<String, Object> properties) {
             return new Point((int) properties.get("x"), (int) 
properties.get("y"));
         }
     }
@@ -202,7 +202,7 @@ public class PdtGraphSONSerializersV4Test extends 
AbstractGraphSONTest {
 
         assertNull(result.getHydrated());
         assertEquals("Point", result.getName());
-        assertEquals(1, result.getProperties().get("x"));
+        assertEquals(1, result.getFields().get("x"));
     }
 
     @Test
@@ -225,6 +225,6 @@ public class PdtGraphSONSerializersV4Test extends 
AbstractGraphSONTest {
 
         assertNull(result.getHydrated());
         assertEquals("Unknown", result.getName());
-        assertEquals(1, result.getProperties().get("a"));
+        assertEquals(1, result.getFields().get("a"));
     }
 }
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeRegistryTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeRegistryTest.java
index 13f9a05b59..acc2b01174 100644
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeRegistryTest.java
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeRegistryTest.java
@@ -43,13 +43,13 @@ public class ProviderDefinedTypeRegistryTest {
     static class PointAdapter implements ProviderDefinedTypeAdapter<Point> {
         @Override public String typeName() { return "Point"; }
         @Override public Class<Point> targetClass() { return Point.class; }
-        @Override public Map<String, Object> toProperties(Point obj) {
+        @Override public Map<String, Object> toFields(Point obj) {
             final Map<String, Object> m = new HashMap<>();
             m.put("x", obj.x);
             m.put("y", obj.y);
             return m;
         }
-        @Override public Point fromProperties(Map<String, Object> properties) {
+        @Override public Point fromFields(Map<String, Object> properties) {
             return new Point((int) properties.get("x"), (int) 
properties.get("y"));
         }
     }
@@ -64,13 +64,13 @@ public class ProviderDefinedTypeRegistryTest {
     static class LineAdapter implements ProviderDefinedTypeAdapter<Line> {
         @Override public String typeName() { return "Line"; }
         @Override public Class<Line> targetClass() { return Line.class; }
-        @Override public Map<String, Object> toProperties(Line obj) {
+        @Override public Map<String, Object> toFields(Line obj) {
             final Map<String, Object> m = new HashMap<>();
             m.put("start", obj.start);
             m.put("end", obj.end);
             return m;
         }
-        @Override public Line fromProperties(Map<String, Object> properties) {
+        @Override public Line fromFields(Map<String, Object> properties) {
             return new Line((Point) properties.get("start"), (Point) 
properties.get("end"));
         }
     }
@@ -79,8 +79,8 @@ public class ProviderDefinedTypeRegistryTest {
     static class FailingAdapter implements ProviderDefinedTypeAdapter<Point> {
         @Override public String typeName() { return "Failing"; }
         @Override public Class<Point> targetClass() { return Point.class; }
-        @Override public Map<String, Object> toProperties(Point obj) { return 
new HashMap<>(); }
-        @Override public Point fromProperties(Map<String, Object> properties) {
+        @Override public Map<String, Object> toFields(Point obj) { return new 
HashMap<>(); }
+        @Override public Point fromFields(Map<String, Object> properties) {
             throw new RuntimeException("intentional failure");
         }
     }
@@ -162,7 +162,7 @@ public class ProviderDefinedTypeRegistryTest {
         final ProviderDefinedType linePdt = new ProviderDefinedType("Line", 
lineProps);
 
         // Line adapter will receive ProviderDefinedType values for start/end 
since Point is not registered.
-        // The LineAdapter.fromProperties casts to Point which will throw 
ClassCastException,
+        // The LineAdapter.fromFields casts to Point which will throw 
ClassCastException,
         // so hydrate should fall back to returning the raw PDT.
         final Object result = registry.hydrate(linePdt);
         assertSame(linePdt, result);
@@ -202,13 +202,13 @@ public class ProviderDefinedTypeRegistryTest {
     static class PolygonAdapter implements ProviderDefinedTypeAdapter<Polygon> 
{
         @Override public String typeName() { return "Polygon"; }
         @Override public Class<Polygon> targetClass() { return Polygon.class; }
-        @Override public Map<String, Object> toProperties(Polygon obj) {
+        @Override public Map<String, Object> toFields(Polygon obj) {
             final Map<String, Object> m = new HashMap<>();
             m.put("vertices", obj.vertices);
             return m;
         }
         @SuppressWarnings("unchecked")
-        @Override public Polygon fromProperties(Map<String, Object> 
properties) {
+        @Override public Polygon fromFields(Map<String, Object> properties) {
             return new Polygon((List<Point>) properties.get("vertices"));
         }
     }
@@ -249,9 +249,9 @@ public class ProviderDefinedTypeRegistryTest {
         registry.register(new ProviderDefinedTypeAdapter<Map>() {
             @Override public String typeName() { return "PointMap"; }
             @Override public Class<Map> targetClass() { return Map.class; }
-            @Override public Map<String, Object> toProperties(Map obj) { 
return new HashMap<>(); }
+            @Override public Map<String, Object> toFields(Map obj) { return 
new HashMap<>(); }
             @SuppressWarnings("unchecked")
-            @Override public Map fromProperties(Map<String, Object> 
properties) {
+            @Override public Map fromFields(Map<String, Object> properties) {
                 return (Map<String, Object>) properties.get("points");
             }
         });
@@ -283,7 +283,7 @@ public class ProviderDefinedTypeRegistryTest {
     public void shouldBuildViaServiceLoader() {
         // ServiceLoader.load will find adapters on the classpath. With no 
META-INF/services file
         // in test scope, this should produce an empty registry that still 
functions.
-        final ProviderDefinedTypeRegistry registry = 
ProviderDefinedTypeRegistry.build();
+        final ProviderDefinedTypeRegistry registry = 
ProviderDefinedTypeRegistry.create();
 
         final Map<String, Object> props = new HashMap<>();
         props.put("x", 1);
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeTest.java
index 2c153700c8..d39d152951 100644
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeTest.java
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeTest.java
@@ -99,7 +99,7 @@ public class ProviderDefinedTypeTest {
         props.put("y", 2);
         final ProviderDefinedType pdt = new ProviderDefinedType("Point", 
props);
         assertEquals("Point", pdt.getName());
-        assertEquals(props, pdt.getProperties());
+        assertEquals(props, pdt.getFields());
     }
 
     @Test
@@ -108,7 +108,7 @@ public class ProviderDefinedTypeTest {
         props.put("x", 1);
         final ProviderDefinedType pdt = new ProviderDefinedType("Point", 
props);
         props.put("y", 2);
-        assertEquals(1, pdt.getProperties().size());
+        assertEquals(1, pdt.getFields().size());
     }
 
     @Test
@@ -116,15 +116,15 @@ public class ProviderDefinedTypeTest {
         final Map<String, Object> props = new HashMap<>();
         props.put("x", 1);
         final ProviderDefinedType pdt = new ProviderDefinedType("Point", 
props);
-        assertThrows(UnsupportedOperationException.class, () -> 
pdt.getProperties().put("y", 2));
+        assertThrows(UnsupportedOperationException.class, () -> 
pdt.getFields().put("y", 2));
     }
 
     @Test
     public void shouldCreateFromAnnotatedObject() {
         final ProviderDefinedType pdt = ProviderDefinedType.from(new Point());
         assertEquals("Point", pdt.getName());
-        assertEquals(1, pdt.getProperties().get("x"));
-        assertEquals(2, pdt.getProperties().get("y"));
+        assertEquals(1, pdt.getFields().get("x"));
+        assertEquals(2, pdt.getFields().get("y"));
     }
 
     @Test
@@ -136,16 +136,16 @@ public class ProviderDefinedTypeTest {
     @Test
     public void shouldFilterWithIncludedFields() {
         final ProviderDefinedType pdt = ProviderDefinedType.from(new 
IncludedFieldsPoint());
-        assertEquals(1, pdt.getProperties().size());
-        assertEquals(10, pdt.getProperties().get("x"));
+        assertEquals(1, pdt.getFields().size());
+        assertEquals(10, pdt.getFields().get("x"));
     }
 
     @Test
     public void shouldFilterWithExcludedFields() {
         final ProviderDefinedType pdt = ProviderDefinedType.from(new 
ExcludedFieldsPoint());
-        assertEquals(2, pdt.getProperties().size());
-        assertEquals(10, pdt.getProperties().get("x"));
-        assertEquals(20, pdt.getProperties().get("y"));
+        assertEquals(2, pdt.getFields().size());
+        assertEquals(10, pdt.getFields().get("x"));
+        assertEquals(20, pdt.getFields().get("y"));
     }
 
     @Test
@@ -189,9 +189,9 @@ public class ProviderDefinedTypeTest {
     @Test
     public void shouldPreserveNullFieldValues() {
         final ProviderDefinedType pdt = ProviderDefinedType.from(new 
NullFieldPoint());
-        assertEquals(2, pdt.getProperties().size());
-        assertEquals(null, pdt.getProperties().get("label"));
-        assertEquals(5, pdt.getProperties().get("x"));
+        assertEquals(2, pdt.getFields().size());
+        assertEquals(null, pdt.getFields().get("label"));
+        assertEquals(5, pdt.getFields().get("x"));
     }
 
     @Test
@@ -203,25 +203,25 @@ public class ProviderDefinedTypeTest {
     public void shouldIncludeInheritedFields() {
         final ProviderDefinedType pdt = ProviderDefinedType.from(new 
InheritedPoint());
         assertEquals("GeoPoint", pdt.getName());
-        assertEquals(3, pdt.getProperties().size());
-        assertEquals("origin", pdt.getProperties().get("label"));
-        assertEquals(1, pdt.getProperties().get("x"));
-        assertEquals(2, pdt.getProperties().get("y"));
+        assertEquals(3, pdt.getFields().size());
+        assertEquals("origin", pdt.getFields().get("label"));
+        assertEquals(1, pdt.getFields().get("x"));
+        assertEquals(2, pdt.getFields().get("y"));
     }
 
     @Test
     public void shouldExcludeInheritedFields() {
         final ProviderDefinedType pdt = ProviderDefinedType.from(new 
InheritedExcluded());
-        assertEquals(2, pdt.getProperties().size());
-        assertEquals("test", pdt.getProperties().get("label"));
-        assertEquals(1, pdt.getProperties().get("x"));
+        assertEquals(2, pdt.getFields().size());
+        assertEquals("test", pdt.getFields().get("label"));
+        assertEquals(1, pdt.getFields().get("x"));
     }
 
     @Test
     public void shouldIncludeOnlySpecifiedFieldsAcrossHierarchy() {
         final ProviderDefinedType pdt = ProviderDefinedType.from(new 
InheritedIncluded());
-        assertEquals(2, pdt.getProperties().size());
-        assertEquals("included", pdt.getProperties().get("label"));
-        assertEquals(1, pdt.getProperties().get("x"));
+        assertEquals(2, pdt.getFields().size());
+        assertEquals("included", pdt.getFields().get("label"));
+        assertEquals(1, pdt.getFields().get("x"));
     }
 }
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GremlinLang.cs 
b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GremlinLang.cs
index bb48d96bc6..b6d1d24267 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GremlinLang.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GremlinLang.cs
@@ -340,14 +340,14 @@ namespace Gremlin.Net.Process.Traversal
             if (arg is ProviderDefinedType pdt)
             {
                 var sb2 = new StringBuilder("[");
-                var count = pdt.Properties.Count;
+                var count = pdt.Fields.Count;
                 if (count == 0)
                 {
                     sb2.Append(':');
                 }
                 else
                 {
-                    foreach (var kvp in pdt.Properties)
+                    foreach (var kvp in pdt.Fields)
                     {
                         
sb2.Append(ArgAsString(kvp.Key)).Append(':').Append(ArgAsString(kvp.Value));
                         if (--count > 0) sb2.Append(',');
@@ -382,8 +382,8 @@ namespace Gremlin.Net.Process.Traversal
                 var adapterInfo = PdtRegistry.GetAdapterByType(arg.GetType());
                 if (adapterInfo != null)
                 {
-                    var (adapterTypeName, toProperties) = adapterInfo.Value;
-                    var props = toProperties(arg);
+                    var (adapterTypeName, toFields) = adapterInfo.Value;
+                    var props = toFields(arg);
                     return ArgAsString(new ProviderDefinedType(adapterTypeName,
                         new Dictionary<string, object?>(props)));
                 }
diff --git 
a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary4/Types/CompositePDTSerializer.cs
 
b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary4/Types/CompositePDTSerializer.cs
index 49c4bdff66..10e2a082fa 100644
--- 
a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary4/Types/CompositePDTSerializer.cs
+++ 
b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary4/Types/CompositePDTSerializer.cs
@@ -47,8 +47,8 @@ namespace Gremlin.Net.Structure.IO.GraphBinary4.Types
         {
             // Write name as fully-qualified string
             await writer.WriteAsync(value.Name, stream, 
cancellationToken).ConfigureAwait(false);
-            // Write properties as fully-qualified map
-            await writer.WriteAsync((IDictionary<string, object?>)new 
Dictionary<string, object?>(value.Properties),
+            // Write fields as fully-qualified map
+            await writer.WriteAsync((IDictionary<string, object?>)new 
Dictionary<string, object?>(value.Fields),
                 stream, cancellationToken).ConfigureAwait(false);
         }
 
@@ -63,16 +63,16 @@ namespace Gremlin.Net.Structure.IO.GraphBinary4.Types
             var map = await reader.ReadAsync(stream, 
cancellationToken).ConfigureAwait(false)
                 as IDictionary<object, object?>;
 
-            var properties = new Dictionary<string, object?>();
+            var fields = new Dictionary<string, object?>();
             if (map != null)
             {
                 foreach (var kv in map)
                 {
-                    properties[(string)kv.Key] = kv.Value;
+                    fields[(string)kv.Key] = kv.Value;
                 }
             }
 
-            return new ProviderDefinedType(name!, properties);
+            return new ProviderDefinedType(name!, fields);
         }
     }
 }
diff --git 
a/gremlin-dotnet/src/Gremlin.Net/Structure/IProviderDefinedTypeAdapter.cs 
b/gremlin-dotnet/src/Gremlin.Net/Structure/IProviderDefinedTypeAdapter.cs
index cd7af23e3c..89dce66cfc 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/IProviderDefinedTypeAdapter.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IProviderDefinedTypeAdapter.cs
@@ -37,13 +37,13 @@ namespace Gremlin.Net.Structure
         string TypeName { get; }
 
         /// <summary>
-        /// Creates a typed instance from the PDT properties.
+        /// Creates a typed instance from the PDT fields.
         /// </summary>
-        T FromProperties(IReadOnlyDictionary<string, object?> properties);
+        T FromFields(IReadOnlyDictionary<string, object?> fields);
 
         /// <summary>
-        /// Converts a typed instance back to PDT properties.
+        /// Converts a typed instance back to PDT fields.
         /// </summary>
-        IReadOnlyDictionary<string, object?> ToProperties(T obj);
+        IReadOnlyDictionary<string, object?> ToFields(T obj);
     }
 }
diff --git 
a/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedAttribute.cs 
b/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedAttribute.cs
index c7d25667e5..f9a418e01a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedAttribute.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedAttribute.cs
@@ -67,7 +67,7 @@ namespace Gremlin.Net.Structure
             if (!RegisteredTypes.TryGetValue(pdt.Name, out var type))
                 return pdt;
             var obj = Activator.CreateInstance(type)!;
-            foreach (var (key, value) in pdt.Properties)
+            foreach (var (key, value) in pdt.Fields)
             {
                 var prop = type.GetProperty(key, BindingFlags.Public | 
BindingFlags.Instance);
                 if (prop != null && prop.CanWrite && value != null)
diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedType.cs 
b/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedType.cs
index ac6c9d60f9..69c005c188 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedType.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedType.cs
@@ -28,7 +28,7 @@ using System.Linq;
 namespace Gremlin.Net.Structure
 {
     /// <summary>
-    /// Represents a provider-defined type (PDT) with a name and a set of 
properties.
+    /// Represents a provider-defined type (PDT) with a name and a set of 
fields.
     /// </summary>
     public class ProviderDefinedType
     {
@@ -36,12 +36,12 @@ namespace Gremlin.Net.Structure
         /// Initializes a new instance of the <see 
cref="ProviderDefinedType"/> class.
         /// </summary>
         /// <param name="name">The fully-qualified name of the 
provider-defined type.</param>
-        /// <param name="properties">The properties of the provider-defined 
type.</param>
-        public ProviderDefinedType(string name, IReadOnlyDictionary<string, 
object?> properties)
+        /// <param name="fields">The fields of the provider-defined 
type.</param>
+        public ProviderDefinedType(string name, IReadOnlyDictionary<string, 
object?> fields)
         {
             Name = name ?? throw new ArgumentNullException(nameof(name));
             if (string.IsNullOrEmpty(name)) throw new ArgumentException("name 
cannot be empty", nameof(name));
-            Properties = properties ?? new Dictionary<string, object?>();
+            Fields = fields ?? new Dictionary<string, object?>();
         }
 
         /// <summary>
@@ -50,21 +50,21 @@ namespace Gremlin.Net.Structure
         public string Name { get; }
 
         /// <summary>
-        /// Gets the properties of this provider-defined type.
+        /// Gets the fields of this provider-defined type.
         /// </summary>
-        public IReadOnlyDictionary<string, object?> Properties { get; }
+        public IReadOnlyDictionary<string, object?> Fields { get; }
 
         /// <inheritdoc />
         public override string ToString() =>
-            $"pdt[{Name}]{{{string.Join(", ", Properties.Select(kv => 
$"{kv.Key}={kv.Value}"))}}}";
+            $"pdt[{Name}]{{{string.Join(", ", Fields.Select(kv => 
$"{kv.Key}={kv.Value}"))}}}";
 
         /// <inheritdoc />
         public override bool Equals(object? obj) =>
             obj is ProviderDefinedType other && Name == other.Name &&
-            Properties.Count == other.Properties.Count &&
-            Properties.All(kv => other.Properties.TryGetValue(kv.Key, out var 
v) && Equals(kv.Value, v));
+            Fields.Count == other.Fields.Count &&
+            Fields.All(kv => other.Fields.TryGetValue(kv.Key, out var v) && 
Equals(kv.Value, v));
 
         /// <inheritdoc />
-        public override int GetHashCode() => HashCode.Combine(Name, 
Properties.Count);
+        public override int GetHashCode() => HashCode.Combine(Name, 
Fields.Count);
     }
 }
diff --git 
a/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedTypeRegistry.cs 
b/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedTypeRegistry.cs
index b33269c98c..530c7979bf 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedTypeRegistry.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedTypeRegistry.cs
@@ -54,7 +54,7 @@ namespace Gremlin.Net.Structure
         /// <item>Types annotated with <see cref="ProviderDefinedAttribute"/> 
(annotation-based round-trip)</item>
         /// </list>
         /// </summary>
-        public static ProviderDefinedTypeRegistry Build()
+        public static ProviderDefinedTypeRegistry Create()
         {
             var registry = new ProviderDefinedTypeRegistry();
 
@@ -103,13 +103,13 @@ namespace Gremlin.Net.Structure
         }
 
         /// <summary>
-        /// Returns the type name and ToProperties method for the given CLR 
type, or null if not registered.
+        /// Returns the type name and ToFields method for the given CLR type, 
or null if not registered.
         /// </summary>
         internal (string typeName, Func<object, IReadOnlyDictionary<string, 
object?>>)? GetAdapterByType(Type type)
         {
             if (!_adaptersByType.TryGetValue(type, out var entry))
                 return null;
-            var method = entry.adapter.GetType().GetMethod("ToProperties");
+            var method = entry.adapter.GetType().GetMethod("ToFields");
             if (method == null) return null;
             return (entry.typeName, obj => (IReadOnlyDictionary<string, 
object?>)method.Invoke(entry.adapter, new[] { obj })!);
         }
@@ -124,15 +124,15 @@ namespace Gremlin.Net.Structure
                 return pdt;
             try
             {
-                var hydratedProps = new Dictionary<string, object?>();
-                foreach (var (key, value) in pdt.Properties)
+                var hydratedFields = new Dictionary<string, object?>();
+                foreach (var (key, value) in pdt.Fields)
                 {
-                    hydratedProps[key] = value is ProviderDefinedType nested ? 
Hydrate(nested) : value;
+                    hydratedFields[key] = value is ProviderDefinedType nested 
? Hydrate(nested) : value;
                 }
 
-                var readOnlyProps = new ReadOnlyDictionary<string, 
object?>(hydratedProps);
-                var method = adapterObj.GetType().GetMethod("FromProperties");
-                return method!.Invoke(adapterObj, new object[] { readOnlyProps 
})!;
+                var readOnlyFields = new ReadOnlyDictionary<string, 
object?>(hydratedFields);
+                var method = adapterObj.GetType().GetMethod("FromFields");
+                return method!.Invoke(adapterObj, new object[] { 
readOnlyFields })!;
             }
             catch (Exception)
             {
diff --git 
a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/DriverRemoteConnectionTests.cs
 
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/DriverRemoteConnectionTests.cs
index 1f6ce57e01..3aaedb218e 100644
--- 
a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/DriverRemoteConnectionTests.cs
+++ 
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/DriverRemoteConnectionTests.cs
@@ -113,8 +113,8 @@ public class DriverRemoteConnectionTests
         Assert.Single(results);
         var result = Assert.IsType<ProviderDefinedType>(results[0]);
         Assert.Equal("TestPoint", result.Name);
-        Assert.Equal(1, result.Properties["x"]);
-        Assert.Equal(2, result.Properties["y"]);
+        Assert.Equal(1, result.Fields["x"]);
+        Assert.Equal(2, result.Fields["y"]);
     }
 
     [Fact]
@@ -168,16 +168,16 @@ public class DriverRemoteConnectionTests
     {
         public string TypeName => "TestPoint";
 
-        public TestPointClass FromProperties(IReadOnlyDictionary<string, 
object?> properties)
+        public TestPointClass FromFields(IReadOnlyDictionary<string, object?> 
fields)
         {
             return new TestPointClass
             {
-                X = Convert.ToInt32(properties["x"]),
-                Y = Convert.ToInt32(properties["y"])
+                X = Convert.ToInt32(fields["x"]),
+                Y = Convert.ToInt32(fields["y"])
             };
         }
 
-        public IReadOnlyDictionary<string, object?> 
ToProperties(TestPointClass obj)
+        public IReadOnlyDictionary<string, object?> ToFields(TestPointClass 
obj)
         {
             return new ReadOnlyDictionary<string, object?>(
                 new Dictionary<string, object?> { { "x", obj.X }, { "y", obj.Y 
} });
diff --git 
a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs 
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs
index fab9af53e4..a5fdac7c8e 100644
--- 
a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs
+++ 
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs
@@ -219,9 +219,9 @@ namespace Gremlin.Net.IntegrationTest.Driver
             Assert.Single(results);
             var pdt = Assert.IsType<ProviderDefinedType>(results[0]);
             Assert.Equal("Point", pdt.Name);
-            Assert.Equal(2, pdt.Properties.Count);
-            Assert.Equal(1, pdt.Properties["x"]);
-            Assert.Equal(2, pdt.Properties["y"]);
+            Assert.Equal(2, pdt.Fields.Count);
+            Assert.Equal(1, pdt.Fields["x"]);
+            Assert.Equal(2, pdt.Fields["y"]);
         }
 
         [Fact]
@@ -238,14 +238,14 @@ namespace Gremlin.Net.IntegrationTest.Driver
             Assert.Single(results);
             var pdt = Assert.IsType<ProviderDefinedType>(results[0]);
             Assert.Equal("Person", pdt.Name);
-            Assert.Equal("Alice", pdt.Properties["name"]);
-            Assert.Equal(30, pdt.Properties["age"]);
+            Assert.Equal("Alice", pdt.Fields["name"]);
+            Assert.Equal(30, pdt.Fields["age"]);
 
-            var address = 
Assert.IsType<ProviderDefinedType>(pdt.Properties["address"]);
+            var address = 
Assert.IsType<ProviderDefinedType>(pdt.Fields["address"]);
             Assert.Equal("Address", address.Name);
-            Assert.Equal("123 Main St", address.Properties["street"]);
-            Assert.Equal("Springfield", address.Properties["city"]);
-            Assert.Equal("12345", address.Properties["zip"]);
+            Assert.Equal("123 Main St", address.Fields["street"]);
+            Assert.Equal("Springfield", address.Fields["city"]);
+            Assert.Equal("12345", address.Fields["zip"]);
         }
 
         [Fact]
@@ -264,13 +264,13 @@ namespace Gremlin.Net.IntegrationTest.Driver
 
             var p1 = Assert.IsType<ProviderDefinedType>(list[0]);
             Assert.Equal("Point", p1.Name);
-            Assert.Equal(1, p1.Properties["x"]);
-            Assert.Equal(2, p1.Properties["y"]);
+            Assert.Equal(1, p1.Fields["x"]);
+            Assert.Equal(2, p1.Fields["y"]);
 
             var p2 = Assert.IsType<ProviderDefinedType>(list[1]);
             Assert.Equal("Point", p2.Name);
-            Assert.Equal(3, p2.Properties["x"]);
-            Assert.Equal(4, p2.Properties["y"]);
+            Assert.Equal(3, p2.Fields["x"]);
+            Assert.Equal(4, p2.Fields["y"]);
         }
     }
 }
diff --git 
a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/GremlinLangTests.cs
 
b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/GremlinLangTests.cs
index a0c15d1ef5..e6dc565d72 100644
--- 
a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/GremlinLangTests.cs
+++ 
b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/GremlinLangTests.cs
@@ -1203,10 +1203,10 @@ namespace Gremlin.Net.UnitTest.Process.Traversal
         {
             public string TypeName => "adapter.Point";
 
-            public AnnotatedPointWithAdapter 
FromProperties(IReadOnlyDictionary<string, object?> properties) =>
-                new() { X = (int)properties["a"]!, Y = (int)properties["b"]! };
+            public AnnotatedPointWithAdapter 
FromFields(IReadOnlyDictionary<string, object?> fields) =>
+                new() { X = (int)fields["a"]!, Y = (int)fields["b"]! };
 
-            public IReadOnlyDictionary<string, object?> 
ToProperties(AnnotatedPointWithAdapter obj) =>
+            public IReadOnlyDictionary<string, object?> 
ToFields(AnnotatedPointWithAdapter obj) =>
                 new Dictionary<string, object?> { { "a", obj.X }, { "b", obj.Y 
} };
         }
     }
diff --git 
a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary4/ProviderDefinedTypeTests.cs
 
b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary4/ProviderDefinedTypeTests.cs
index 36a6318b52..c8b3b008f8 100644
--- 
a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary4/ProviderDefinedTypeTests.cs
+++ 
b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary4/ProviderDefinedTypeTests.cs
@@ -49,7 +49,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary4
 
             Assert.NotNull(actual);
             Assert.Equal(expected.Name, actual!.Name);
-            Assert.Equal(expected.Properties, actual.Properties);
+            Assert.Equal(expected.Fields, actual.Fields);
         }
 
         [Fact]
@@ -64,7 +64,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary4
 
             Assert.NotNull(actual);
             Assert.Equal(expected.Name, actual!.Name);
-            Assert.Empty(actual.Properties);
+            Assert.Empty(actual.Fields);
         }
 
         [Fact]
@@ -80,7 +80,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary4
 
             Assert.NotNull(actual);
             Assert.Equal(expected.Name, actual!.Name);
-            Assert.Null(actual.Properties["key"]);
+            Assert.Null(actual.Fields["key"]);
         }
 
         [Fact]
diff --git 
a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/ProviderDefinedTypeRegistryTests.cs
 
b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/ProviderDefinedTypeRegistryTests.cs
index a9aefc6ee2..512b3f31d5 100644
--- 
a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/ProviderDefinedTypeRegistryTests.cs
+++ 
b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/ProviderDefinedTypeRegistryTests.cs
@@ -103,17 +103,17 @@ namespace Gremlin.Net.UnitTest.Structure
         }
 
         [Fact]
-        public void BuildShouldReturnRegistryWithoutCrashing()
+        public void CreateShouldReturnRegistryWithoutCrashing()
         {
-            var registry = ProviderDefinedTypeRegistry.Build();
+            var registry = ProviderDefinedTypeRegistry.Create();
 
             Assert.NotNull(registry);
         }
 
         [Fact]
-        public void BuildShouldDiscoverAdapterFromAssembly()
+        public void CreateShouldDiscoverAdapterFromAssembly()
         {
-            var registry = ProviderDefinedTypeRegistry.Build();
+            var registry = ProviderDefinedTypeRegistry.Create();
             var pdt = new ProviderDefinedType("test:Discoverable",
                 new Dictionary<string, object?> { ["value"] = "hello" });
 
@@ -144,10 +144,10 @@ namespace Gremlin.Net.UnitTest.Structure
         {
             public string TypeName => "geo:Point";
 
-            public Point FromProperties(IReadOnlyDictionary<string, object?> 
properties) =>
-                new() { X = (double)properties["x"]!, Y = 
(double)properties["y"]! };
+            public Point FromFields(IReadOnlyDictionary<string, object?> 
fields) =>
+                new() { X = (double)fields["x"]!, Y = (double)fields["y"]! };
 
-            public IReadOnlyDictionary<string, object?> ToProperties(Point 
obj) =>
+            public IReadOnlyDictionary<string, object?> ToFields(Point obj) =>
                 new Dictionary<string, object?> { ["x"] = obj.X, ["y"] = obj.Y 
};
         }
 
@@ -155,10 +155,10 @@ namespace Gremlin.Net.UnitTest.Structure
         {
             public string TypeName => "geo:Line";
 
-            public Line FromProperties(IReadOnlyDictionary<string, object?> 
properties) =>
-                new() { Start = (Point)properties["start"]!, End = 
(Point)properties["end"]! };
+            public Line FromFields(IReadOnlyDictionary<string, object?> 
fields) =>
+                new() { Start = (Point)fields["start"]!, End = 
(Point)fields["end"]! };
 
-            public IReadOnlyDictionary<string, object?> ToProperties(Line obj) 
=>
+            public IReadOnlyDictionary<string, object?> ToFields(Line obj) =>
                 new Dictionary<string, object?> { ["start"] = obj.Start, 
["end"] = obj.End };
         }
 
@@ -166,10 +166,10 @@ namespace Gremlin.Net.UnitTest.Structure
         {
             public string TypeName => "bad:Type";
 
-            public object FromProperties(IReadOnlyDictionary<string, object?> 
properties) =>
+            public object FromFields(IReadOnlyDictionary<string, object?> 
fields) =>
                 throw new InvalidOperationException("intentional failure");
 
-            public IReadOnlyDictionary<string, object?> ToProperties(object 
obj) =>
+            public IReadOnlyDictionary<string, object?> ToFields(object obj) =>
                 throw new InvalidOperationException("intentional failure");
         }
 
@@ -187,10 +187,10 @@ namespace Gremlin.Net.UnitTest.Structure
     {
         public string TypeName => "test:Discoverable";
 
-        public DiscoverableType FromProperties(IReadOnlyDictionary<string, 
object?> properties) =>
-            new() { Value = (string)properties["value"]! };
+        public DiscoverableType FromFields(IReadOnlyDictionary<string, 
object?> fields) =>
+            new() { Value = (string)fields["value"]! };
 
-        public IReadOnlyDictionary<string, object?> 
ToProperties(DiscoverableType obj) =>
+        public IReadOnlyDictionary<string, object?> ToFields(DiscoverableType 
obj) =>
             new Dictionary<string, object?> { ["value"] = obj.Value };
     }
 }
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 3643aa9415..6c2fea1e71 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
@@ -55,7 +55,10 @@ public class DriverRemoteConnection implements 
RemoteConnection {
     private transient Optional<Configuration> conf = Optional.empty();
 
     private final boolean attachElements;
-    private ProviderDefinedTypeRegistry pdtRegistry;
+
+    // Default to SPI-discovered adapters so PDT dehydration works with zero 
configuration.
+    // This performs a lightweight ServiceLoader scan; the serializer path 
does its own independent scan.
+    private ProviderDefinedTypeRegistry pdtRegistry = 
ProviderDefinedTypeRegistry.create();
 
     public DriverRemoteConnection(final Configuration conf) {
         final boolean hasClusterConf = IteratorUtils.anyMatch(conf.getKeys(), 
k -> k.startsWith("clusterConfiguration"));
diff --git a/gremlin-go/driver/client_test.go b/gremlin-go/driver/client_test.go
index c234a99918..ffffcad5cb 100644
--- a/gremlin-go/driver/client_test.go
+++ b/gremlin-go/driver/client_test.go
@@ -318,8 +318,8 @@ func TestProviderDefinedTypeIntegration(t *testing.T) {
                pdt, ok := result.Data.(*ProviderDefinedType)
                require.True(t, ok, "expected *ProviderDefinedType, got %T", 
result.Data)
                assert.Equal(t, "Point", pdt.Name)
-               assert.Equal(t, int32(1), pdt.Properties["x"])
-               assert.Equal(t, int32(2), pdt.Properties["y"])
+               assert.Equal(t, int32(1), pdt.Fields["x"])
+               assert.Equal(t, int32(2), pdt.Fields["y"])
        })
 
        t.Run("nested PDT (Person with Address)", func(t *testing.T) {
@@ -343,15 +343,15 @@ func TestProviderDefinedTypeIntegration(t *testing.T) {
                pdt, ok := result.Data.(*ProviderDefinedType)
                require.True(t, ok, "expected *ProviderDefinedType, got %T", 
result.Data)
                assert.Equal(t, "Person", pdt.Name)
-               assert.Equal(t, "Alice", pdt.Properties["name"])
-               assert.Equal(t, int32(30), pdt.Properties["age"])
+               assert.Equal(t, "Alice", pdt.Fields["name"])
+               assert.Equal(t, int32(30), pdt.Fields["age"])
 
-               address, ok := pdt.Properties["address"].(*ProviderDefinedType)
+               address, ok := pdt.Fields["address"].(*ProviderDefinedType)
                require.True(t, ok, "expected nested *ProviderDefinedType for 
address")
                assert.Equal(t, "Address", address.Name)
-               assert.Equal(t, "123 Main St", address.Properties["street"])
-               assert.Equal(t, "Springfield", address.Properties["city"])
-               assert.Equal(t, "12345", address.Properties["zip"])
+               assert.Equal(t, "123 Main St", address.Fields["street"])
+               assert.Equal(t, "Springfield", address.Fields["city"])
+               assert.Equal(t, "12345", address.Fields["zip"])
        })
 
        t.Run("PDT in collection", func(t *testing.T) {
@@ -378,13 +378,13 @@ func TestProviderDefinedTypeIntegration(t *testing.T) {
                p1, ok := list[0].(*ProviderDefinedType)
                require.True(t, ok)
                assert.Equal(t, "Point", p1.Name)
-               assert.Equal(t, int32(1), p1.Properties["x"])
-               assert.Equal(t, int32(2), p1.Properties["y"])
+               assert.Equal(t, int32(1), p1.Fields["x"])
+               assert.Equal(t, int32(2), p1.Fields["y"])
 
                p2, ok := list[1].(*ProviderDefinedType)
                require.True(t, ok)
                assert.Equal(t, "Point", p2.Name)
-               assert.Equal(t, int32(3), p2.Properties["x"])
-               assert.Equal(t, int32(4), p2.Properties["y"])
+               assert.Equal(t, int32(3), p2.Fields["x"])
+               assert.Equal(t, int32(4), p2.Fields["y"])
        })
 }
\ No newline at end of file
diff --git a/gremlin-go/driver/graphBinaryDeserializer.go 
b/gremlin-go/driver/graphBinaryDeserializer.go
index 8b20080cb0..dda90cfa52 100644
--- a/gremlin-go/driver/graphBinaryDeserializer.go
+++ b/gremlin-go/driver/graphBinaryDeserializer.go
@@ -639,14 +639,14 @@ func (d *GraphBinaryDeserializer) readCompositePDT() 
(interface{}, error) {
        if propsObj != nil {
                raw, ok := propsObj.(map[interface{}]interface{})
                if !ok {
-                       return nil, fmt.Errorf("ProviderDefinedType properties 
must be a map")
+                       return nil, fmt.Errorf("ProviderDefinedType fields must 
be a map")
                }
                props = make(map[string]interface{}, len(raw))
                for k, v := range raw {
                        props[fmt.Sprint(k)] = v
                }
        }
-       pdt := &ProviderDefinedType{Name: name, Properties: props}
+       pdt := &ProviderDefinedType{Name: name, Fields: props}
        if d.pdtRegistry != nil {
                hydrated := d.pdtRegistry.Hydrate(pdt)
                if hydrated != pdt {
diff --git a/gremlin-go/driver/graphBinarySerializer_test.go 
b/gremlin-go/driver/graphBinarySerializer_test.go
index ea43a45e6d..e6f8cda81b 100644
--- a/gremlin-go/driver/graphBinarySerializer_test.go
+++ b/gremlin-go/driver/graphBinarySerializer_test.go
@@ -541,8 +541,8 @@ func TestProviderDefinedTypeSerialization(t *testing.T) {
 
        t.Run("round-trip simple PDT", func(t *testing.T) {
                source := &ProviderDefinedType{
-                       Name:       "com.example.MyType",
-                       Properties: map[string]interface{}{"key": "value", 
"num": int32(42)},
+                       Name:   "com.example.MyType",
+                       Fields: map[string]interface{}{"key": "value", "num": 
int32(42)},
                }
                var buf bytes.Buffer
                err := serializer.write(source, &buf)
@@ -554,18 +554,18 @@ func TestProviderDefinedTypeSerialization(t *testing.T) {
                pdt, ok := result.(*ProviderDefinedType)
                assert.True(t, ok)
                assert.Equal(t, source.Name, pdt.Name)
-               assert.Equal(t, source.Properties["key"], pdt.Properties["key"])
-               assert.Equal(t, source.Properties["num"], pdt.Properties["num"])
+               assert.Equal(t, source.Fields["key"], pdt.Fields["key"])
+               assert.Equal(t, source.Fields["num"], pdt.Fields["num"])
        })
 
        t.Run("round-trip nested PDT", func(t *testing.T) {
                inner := &ProviderDefinedType{
-                       Name:       "com.example.Inner",
-                       Properties: map[string]interface{}{"x": int32(1)},
+                       Name:   "com.example.Inner",
+                       Fields: map[string]interface{}{"x": int32(1)},
                }
                outer := &ProviderDefinedType{
-                       Name:       "com.example.Outer",
-                       Properties: map[string]interface{}{"child": inner},
+                       Name:   "com.example.Outer",
+                       Fields: map[string]interface{}{"child": inner},
                }
                var buf bytes.Buffer
                err := serializer.write(outer, &buf)
@@ -577,10 +577,10 @@ func TestProviderDefinedTypeSerialization(t *testing.T) {
                pdt, ok := result.(*ProviderDefinedType)
                assert.True(t, ok)
                assert.Equal(t, "com.example.Outer", pdt.Name)
-               child, ok := pdt.Properties["child"].(*ProviderDefinedType)
+               child, ok := pdt.Fields["child"].(*ProviderDefinedType)
                assert.True(t, ok)
                assert.Equal(t, "com.example.Inner", child.Name)
-               assert.Equal(t, int32(1), child.Properties["x"])
+               assert.Equal(t, int32(1), child.Fields["x"])
        })
 
        t.Run("empty name produces error", func(t *testing.T) {
@@ -603,8 +603,8 @@ func TestProviderDefinedTypeSerialization(t *testing.T) {
                        }, nil)
 
                source := &ProviderDefinedType{
-                       Name:       "com.example.MyType",
-                       Properties: map[string]interface{}{"key": "value"},
+                       Name:   "com.example.MyType",
+                       Fields: map[string]interface{}{"key": "value"},
                }
                var buf bytes.Buffer
                err := serializer.write(source, &buf)
@@ -621,8 +621,8 @@ func TestProviderDefinedTypeSerialization(t *testing.T) {
 
        t.Run("no hydration without registry", func(t *testing.T) {
                source := &ProviderDefinedType{
-                       Name:       "com.example.MyType",
-                       Properties: map[string]interface{}{"key": "value"},
+                       Name:   "com.example.MyType",
+                       Fields: map[string]interface{}{"key": "value"},
                }
                var buf bytes.Buffer
                err := serializer.write(source, &buf)
diff --git a/gremlin-go/driver/gremlinlang.go b/gremlin-go/driver/gremlinlang.go
index dac9e64aa8..c6c36ad128 100644
--- a/gremlin-go/driver/gremlinlang.go
+++ b/gremlin-go/driver/gremlinlang.go
@@ -206,7 +206,7 @@ func (gl *GremlinLang) argAsString(arg interface{}) 
(string, error) {
                name := reflect.ValueOf(v).Type().Name()
                return fmt.Sprintf("%s.%s", strings.ToUpper(name), v), nil
        case *ProviderDefinedType:
-               props := v.Properties
+               props := v.Fields
                if props == nil {
                        props = map[string]interface{}{}
                }
@@ -304,10 +304,10 @@ func (gl *GremlinLang) argAsString(arg interface{}) 
(string, error) {
                // default behavior for a given Go type.
                if gl.pdtRegistry != nil {
                        adapter := 
gl.pdtRegistry.GetAdapterByType(reflect.TypeOf(arg))
-                       if adapter != nil && adapter.ToProperties != nil {
-                               props, err := adapter.ToProperties(arg)
+                       if adapter != nil && adapter.ToFields != nil {
+                               props, err := adapter.ToFields(arg)
                                if err == nil {
-                                       pdt := &ProviderDefinedType{Name: 
adapter.TypeName, Properties: props}
+                                       pdt := &ProviderDefinedType{Name: 
adapter.TypeName, Fields: props}
                                        return gl.argAsString(pdt)
                                }
                        }
diff --git a/gremlin-go/driver/gremlinlang_test.go 
b/gremlin-go/driver/gremlinlang_test.go
index 9ab9b218f0..7794770115 100644
--- a/gremlin-go/driver/gremlinlang_test.go
+++ b/gremlin-go/driver/gremlinlang_test.go
@@ -863,7 +863,7 @@ func Test_ConvertParametersToString(t *testing.T) {
 func Test_PDT_GremlinLang(t *testing.T) {
        t.Run("basic PDT", func(t *testing.T) {
                g := NewGraphTraversalSource(nil, nil)
-               pdt := &ProviderDefinedType{Name: "MyType", Properties: 
map[string]interface{}{"x": int32(1), "y": "hello"}}
+               pdt := &ProviderDefinedType{Name: "MyType", Fields: 
map[string]interface{}{"x": int32(1), "y": "hello"}}
                gremlin := g.Inject(pdt).GremlinLang.GetGremlin()
                expected := `g.inject(PDT("MyType",["x":1,"y":"hello"]))`
                if gremlin != expected {
@@ -873,7 +873,7 @@ func Test_PDT_GremlinLang(t *testing.T) {
 
        t.Run("empty PDT", func(t *testing.T) {
                g := NewGraphTraversalSource(nil, nil)
-               pdt := &ProviderDefinedType{Name: "Empty", Properties: 
map[string]interface{}{}}
+               pdt := &ProviderDefinedType{Name: "Empty", Fields: 
map[string]interface{}{}}
                gremlin := g.Inject(pdt).GremlinLang.GetGremlin()
                expected := `g.inject(PDT("Empty",[:]))`
                if gremlin != expected {
@@ -883,7 +883,7 @@ func Test_PDT_GremlinLang(t *testing.T) {
 
        t.Run("PDT with special characters in name", func(t *testing.T) {
                g := NewGraphTraversalSource(nil, nil)
-               pdt := &ProviderDefinedType{Name: `say"hello"`, Properties: 
map[string]interface{}{"v": int32(1)}}
+               pdt := &ProviderDefinedType{Name: `say"hello"`, Fields: 
map[string]interface{}{"v": int32(1)}}
                gremlin := g.Inject(pdt).GremlinLang.GetGremlin()
                expected := `g.inject(PDT("say\"hello\"",["v":1]))`
                if gremlin != expected {
@@ -893,7 +893,7 @@ func Test_PDT_GremlinLang(t *testing.T) {
 
        t.Run("PDT with backslash in name", func(t *testing.T) {
                g := NewGraphTraversalSource(nil, nil)
-               pdt := &ProviderDefinedType{Name: `back\slash`, Properties: 
map[string]interface{}{"v": int32(1)}}
+               pdt := &ProviderDefinedType{Name: `back\slash`, Fields: 
map[string]interface{}{"v": int32(1)}}
                gremlin := g.Inject(pdt).GremlinLang.GetGremlin()
                expected := `g.inject(PDT("back\\slash",["v":1]))`
                if gremlin != expected {
@@ -903,8 +903,8 @@ func Test_PDT_GremlinLang(t *testing.T) {
 
        t.Run("nested PDT", func(t *testing.T) {
                g := NewGraphTraversalSource(nil, nil)
-               inner := &ProviderDefinedType{Name: "Inner", Properties: 
map[string]interface{}{"v": int32(1)}}
-               outer := &ProviderDefinedType{Name: "Outer", Properties: 
map[string]interface{}{"inner": inner}}
+               inner := &ProviderDefinedType{Name: "Inner", Fields: 
map[string]interface{}{"v": int32(1)}}
+               outer := &ProviderDefinedType{Name: "Outer", Fields: 
map[string]interface{}{"inner": inner}}
                gremlin := g.Inject(outer).GremlinLang.GetGremlin()
                expected := 
`g.inject(PDT("Outer",["inner":PDT("Inner",["v":1])]))`
                if gremlin != expected {
@@ -914,7 +914,7 @@ func Test_PDT_GremlinLang(t *testing.T) {
 
        t.Run("PDT map keys sorted", func(t *testing.T) {
                g := NewGraphTraversalSource(nil, nil)
-               pdt := &ProviderDefinedType{Name: "T", Properties: 
map[string]interface{}{"z": int32(3), "a": int32(1), "m": int32(2)}}
+               pdt := &ProviderDefinedType{Name: "T", Fields: 
map[string]interface{}{"z": int32(3), "a": int32(1), "m": int32(2)}}
                gremlin := g.Inject(pdt).GremlinLang.GetGremlin()
                expected := `g.inject(PDT("T",["a":1,"m":2,"z":3]))`
                if gremlin != expected {
diff --git a/gremlin-go/driver/pdtRegistry.go b/gremlin-go/driver/pdtRegistry.go
index 1d14feec6c..8dd81bcb47 100644
--- a/gremlin-go/driver/pdtRegistry.go
+++ b/gremlin-go/driver/pdtRegistry.go
@@ -23,9 +23,9 @@ import "reflect"
 
 // PDTAdapter defines how to hydrate/dehydrate a provider-defined type.
 type PDTAdapter struct {
-       TypeName       string
-       FromProperties func(map[string]interface{}) (interface{}, error)
-       ToProperties   func(interface{}) (map[string]interface{}, error)
+       TypeName  string
+       FromFields func(map[string]interface{}) (interface{}, error)
+       ToFields   func(interface{}) (map[string]interface{}, error)
 }
 
 // PDTRegistry maps type names to their hydration adapters.
@@ -41,13 +41,13 @@ func NewPDTRegistry() *PDTRegistry {
 
 // RegisterFuncs registers hydration/dehydration functions for a type name.
 func (r *PDTRegistry) RegisterFuncs(typeName string, fromProps 
func(map[string]interface{}) (interface{}, error), toProps func(interface{}) 
(map[string]interface{}, error)) {
-       adapter := &PDTAdapter{TypeName: typeName, FromProperties: fromProps, 
ToProperties: toProps}
+       adapter := &PDTAdapter{TypeName: typeName, FromFields: fromProps, 
ToFields: toProps}
        r.adaptersByName[typeName] = adapter
 }
 
 // RegisterFuncsWithType registers hydration/dehydration functions for a type 
name and associates a Go type for dehydration lookup.
 func (r *PDTRegistry) RegisterFuncsWithType(typeName string, targetType 
reflect.Type, fromProps func(map[string]interface{}) (interface{}, error), 
toProps func(interface{}) (map[string]interface{}, error)) {
-       adapter := &PDTAdapter{TypeName: typeName, FromProperties: fromProps, 
ToProperties: toProps}
+       adapter := &PDTAdapter{TypeName: typeName, FromFields: fromProps, 
ToFields: toProps}
        r.adaptersByName[typeName] = adapter
        r.adaptersByType[targetType] = adapter
 }
@@ -56,7 +56,7 @@ func (r *PDTRegistry) RegisterFuncsWithType(typeName string, 
targetType reflect.
 func (r *PDTRegistry) RegisterType(typeName string, targetType reflect.Type) {
        r.adaptersByName[typeName] = &PDTAdapter{
                TypeName: typeName,
-               FromProperties: func(props map[string]interface{}) 
(interface{}, error) {
+               FromFields: func(props map[string]interface{}) (interface{}, 
error) {
                        obj := reflect.New(targetType).Elem()
                        for i := 0; i < targetType.NumField(); i++ {
                                field := targetType.Field(i)
@@ -88,15 +88,15 @@ func (r *PDTRegistry) Hydrate(pdt *ProviderDefinedType) 
interface{} {
        if !ok {
                return pdt
        }
-       hydratedProps := make(map[string]interface{}, len(pdt.Properties))
-       for k, v := range pdt.Properties {
+       hydratedFields := make(map[string]interface{}, len(pdt.Fields))
+       for k, v := range pdt.Fields {
                if nested, ok := v.(*ProviderDefinedType); ok {
-                       hydratedProps[k] = r.Hydrate(nested)
+                       hydratedFields[k] = r.Hydrate(nested)
                } else {
-                       hydratedProps[k] = v
+                       hydratedFields[k] = v
                }
        }
-       result, err := adapter.FromProperties(hydratedProps)
+       result, err := adapter.FromFields(hydratedFields)
        if err != nil {
                return pdt
        }
diff --git a/gremlin-go/driver/pdtRegistry_test.go 
b/gremlin-go/driver/pdtRegistry_test.go
index 18a97566d8..cbd4ef1a98 100644
--- a/gremlin-go/driver/pdtRegistry_test.go
+++ b/gremlin-go/driver/pdtRegistry_test.go
@@ -33,14 +33,14 @@ func TestPDTRegistryRegisterFuncsAndHydrate(t *testing.T) {
                return [2]int{props["x"].(int), props["y"].(int)}, nil
        }, nil)
 
-       pdt := &ProviderDefinedType{Name: "x:Point", Properties: 
map[string]interface{}{"x": 1, "y": 2}}
+       pdt := &ProviderDefinedType{Name: "x:Point", Fields: 
map[string]interface{}{"x": 1, "y": 2}}
        result := reg.Hydrate(pdt)
        assert.Equal(t, [2]int{1, 2}, result)
 }
 
 func TestPDTRegistryNoAdapterReturnsRawPDT(t *testing.T) {
        reg := NewPDTRegistry()
-       pdt := &ProviderDefinedType{Name: "x:Unknown", Properties: 
map[string]interface{}{"a": "b"}}
+       pdt := &ProviderDefinedType{Name: "x:Unknown", Fields: 
map[string]interface{}{"a": "b"}}
        result := reg.Hydrate(pdt)
        assert.Equal(t, pdt, result)
 }
@@ -51,7 +51,7 @@ func TestPDTRegistryAdapterErrorReturnsRawPDT(t *testing.T) {
                return nil, errors.New("fail")
        }, nil)
 
-       pdt := &ProviderDefinedType{Name: "x:Bad", Properties: 
map[string]interface{}{}}
+       pdt := &ProviderDefinedType{Name: "x:Bad", Fields: 
map[string]interface{}{}}
        result := reg.Hydrate(pdt)
        assert.Equal(t, pdt, result)
 }
@@ -65,8 +65,8 @@ func TestPDTRegistryNestedHydration(t *testing.T) {
                return "outer:" + props["child"].(string), nil
        }, nil)
 
-       inner := &ProviderDefinedType{Name: "x:Inner", Properties: 
map[string]interface{}{"val": "hi"}}
-       outer := &ProviderDefinedType{Name: "x:Outer", Properties: 
map[string]interface{}{"child": inner}}
+       inner := &ProviderDefinedType{Name: "x:Inner", Fields: 
map[string]interface{}{"val": "hi"}}
+       outer := &ProviderDefinedType{Name: "x:Outer", Fields: 
map[string]interface{}{"child": inner}}
        result := reg.Hydrate(outer)
        assert.Equal(t, "outer:hi!", result)
 }
@@ -81,7 +81,7 @@ func TestPDTRegistryRegisterType(t *testing.T) {
        reg := NewPDTRegistry()
        reg.RegisterType("x:Point", reflect.TypeOf(testPoint{}))
 
-       pdt := &ProviderDefinedType{Name: "x:Point", Properties: 
map[string]interface{}{"x": 3, "y": 4, "L": "label"}}
+       pdt := &ProviderDefinedType{Name: "x:Point", Fields: 
map[string]interface{}{"x": 3, "y": 4, "L": "label"}}
        result := reg.Hydrate(pdt)
        assert.Equal(t, testPoint{X: 3, Y: 4, L: "label"}, result)
 }
diff --git a/gremlin-go/driver/providerDefinedType.go 
b/gremlin-go/driver/providerDefinedType.go
index c2d969f67e..2a5a359892 100644
--- a/gremlin-go/driver/providerDefinedType.go
+++ b/gremlin-go/driver/providerDefinedType.go
@@ -26,25 +26,25 @@ import (
 
 // ProviderDefinedType represents a provider-defined type (PDT) in GraphBinary 
serialization.
 type ProviderDefinedType struct {
-       Name       string
-       Properties map[string]interface{}
+       Name   string
+       Fields map[string]interface{}
 }
 
 func (p *ProviderDefinedType) String() string {
-       return fmt.Sprintf("pdt[%s]%v", p.Name, p.Properties)
+       return fmt.Sprintf("pdt[%s]%v", p.Name, p.Fields)
 }
 
-// pdtWriter serializes a ProviderDefinedType as a fully-qualified string 
(name) followed by a fully-qualified map (properties).
+// pdtWriter serializes a ProviderDefinedType as a fully-qualified string 
(name) followed by a fully-qualified map (fields).
 func pdtWriter(value interface{}, w io.Writer, typeSerializer 
*graphBinaryTypeSerializer) error {
        pdt := value.(*ProviderDefinedType)
        if err := typeSerializer.write(pdt.Name, w); err != nil {
                return err
        }
-       if pdt.Properties == nil {
+       if pdt.Fields == nil {
                return typeSerializer.write(map[interface{}]interface{}{}, w)
        }
-       m := make(map[interface{}]interface{}, len(pdt.Properties))
-       for k, v := range pdt.Properties {
+       m := make(map[interface{}]interface{}, len(pdt.Fields))
+       for k, v := range pdt.Fields {
                m[k] = v
        }
        return typeSerializer.write(m, w)
diff --git a/gremlin-go/driver/providerDefinedType_test.go 
b/gremlin-go/driver/providerDefinedType_test.go
index 91963456d8..8d0f394e24 100644
--- a/gremlin-go/driver/providerDefinedType_test.go
+++ b/gremlin-go/driver/providerDefinedType_test.go
@@ -28,8 +28,8 @@ import (
 func TestProviderDefinedType(t *testing.T) {
        t.Run("String method", func(t *testing.T) {
                pdt := &ProviderDefinedType{
-                       Name:       "com.example.Test",
-                       Properties: map[string]interface{}{"a": int32(1)},
+                       Name:   "com.example.Test",
+                       Fields: map[string]interface{}{"a": int32(1)},
                }
                assert.Contains(t, pdt.String(), "pdt[com.example.Test]")
        })
diff --git a/gremlin-go/driver/traversal_test.go 
b/gremlin-go/driver/traversal_test.go
index bc842f1008..f26c241855 100644
--- a/gremlin-go/driver/traversal_test.go
+++ b/gremlin-go/driver/traversal_test.go
@@ -872,7 +872,7 @@ func TestProviderDefinedTypeTraversalAPIIntegration(t 
*testing.T) {
                defer remote.Close()
 
                g := Traversal_().With(remote)
-               pdt := &ProviderDefinedType{Name: "TestPoint", Properties: 
map[string]interface{}{"x": int32(1), "y": int32(2)}}
+               pdt := &ProviderDefinedType{Name: "TestPoint", Fields: 
map[string]interface{}{"x": int32(1), "y": int32(2)}}
 
                results, err := g.Inject(pdt).ToList()
                require.NoError(t, err)
@@ -881,8 +881,8 @@ func TestProviderDefinedTypeTraversalAPIIntegration(t 
*testing.T) {
                result, ok := results[0].GetInterface().(*ProviderDefinedType)
                require.True(t, ok, "expected *ProviderDefinedType, got %T", 
results[0].GetInterface())
                assert.Equal(t, "TestPoint", result.Name)
-               assert.Equal(t, int32(1), result.Properties["x"])
-               assert.Equal(t, int32(2), result.Properties["y"])
+               assert.Equal(t, int32(1), result.Fields["x"])
+               assert.Equal(t, int32(2), result.Fields["y"])
        })
 
        t.Run("registry-based round-trip via typed struct", func(t *testing.T) {
diff --git a/gremlin-python/src/main/python/gremlin_python/process/traversal.py 
b/gremlin-python/src/main/python/gremlin_python/process/traversal.py
index 6b8bcbfea3..b4e4a788ed 100644
--- a/gremlin-python/src/main/python/gremlin_python/process/traversal.py
+++ b/gremlin-python/src/main/python/gremlin_python/process/traversal.py
@@ -907,7 +907,7 @@ class GremlinLang(object):
                 return tmp
 
         if isinstance(arg, ProviderDefinedType):
-            return 
f'PDT({self._arg_as_string(arg.name)},{self._process_dict(arg.properties)})'
+            return 
f'PDT({self._arg_as_string(arg.name)},{self._process_dict(arg.fields)})'
 
         if isinstance(arg, Vertex):
             return f'{self._arg_as_string(arg.id)}'
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 6160af3c10..5105013811 100644
--- a/gremlin-python/src/main/python/gremlin_python/structure/graph.py
+++ b/gremlin-python/src/main/python/gremlin_python/structure/graph.py
@@ -144,33 +144,33 @@ class Path(object):
 
 
 class ProviderDefinedType(object):
-    def __init__(self, name, properties):
+    def __init__(self, name, fields):
         if not name:
             raise ValueError("name cannot be null or empty")
         self._name = name
-        self._properties = dict(properties) if properties else {}
-        if any(not isinstance(k, str) for k in self._properties):
-            raise TypeError("ProviderDefinedType property keys must be 
strings")
+        self._fields = dict(fields) if fields else {}
+        if any(not isinstance(k, str) for k in self._fields):
+            raise TypeError("ProviderDefinedType field keys must be strings")
 
     @property
     def name(self):
         return self._name
 
     @property
-    def properties(self):
-        return self._properties
+    def fields(self):
+        return self._fields
 
     def __eq__(self, other):
-        return isinstance(other, ProviderDefinedType) and self._name == 
other._name and self._properties == other._properties
+        return isinstance(other, ProviderDefinedType) and self._name == 
other._name and self._fields == other._fields
 
     def __hash__(self):
         try:
-            return hash((self._name, frozenset(self._properties.items())))
+            return hash((self._name, frozenset(self._fields.items())))
         except TypeError:
             return hash(self._name)
 
     def __repr__(self):
-        return f"pdt[{self._name}]{self._properties}"
+        return f"pdt[{self._name}]{self._fields}"
 
 
 class ProviderDefinedTypeRegistry(object):
@@ -191,7 +191,7 @@ class ProviderDefinedTypeRegistry(object):
             }
 
     @classmethod
-    def build(cls):
+    def create(cls):
         """Create a registry populated by entry_points discovery.
 
         Providers register adapters via pyproject.toml:
@@ -228,9 +228,9 @@ class ProviderDefinedTypeRegistry(object):
         if adapter is None:
             return pdt
         try:
-            hydrated_props = {k: self.hydrate(v) if isinstance(v, 
ProviderDefinedType) else v
-                             for k, v in pdt.properties.items()}
-            return adapter['deserialize'](hydrated_props)
+            hydrated_fields = {k: self.hydrate(v) if isinstance(v, 
ProviderDefinedType) else v
+                               for k, v in pdt.fields.items()}
+            return adapter['deserialize'](hydrated_fields)
         except Exception as e:
             import logging
             logging.getLogger(__name__).warning(f"PDT hydration failed for 
'{pdt.name}': {e}")
diff --git 
a/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV4.py 
b/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV4.py
index cc5d9518fd..fa1ca12cb5 100644
--- 
a/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV4.py
+++ 
b/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV4.py
@@ -181,7 +181,7 @@ class GraphBinaryReader(object):
         """Hydrate a ProviderDefinedType using a @provider_defined decorated 
class."""
         cls = _pdt_decorated_types[pdt.name]
         props = {}
-        for k, v in pdt.properties.items():
+        for k, v in pdt.fields.items():
             if isinstance(v, ProviderDefinedType) and v.name in 
_pdt_decorated_types:
                 props[k] = self._hydrate_decorated(v)
             elif self.pdt_registry is not None and isinstance(v, 
ProviderDefinedType):
@@ -958,7 +958,7 @@ class ProviderDefinedTypeIO(_GraphBinaryTypeIO):
     def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True):
         cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend)
         StringIO.dictify(obj.name, writer, to_extend)
-        MapIO.dictify(obj.properties, writer, to_extend)
+        MapIO.dictify(obj.fields, writer, to_extend)
         return to_extend
 
     @classmethod
@@ -968,5 +968,5 @@ class ProviderDefinedTypeIO(_GraphBinaryTypeIO):
     @classmethod
     def _read_pdt(cls, b, r):
         name = r.read_object(b)
-        properties = r.read_object(b)
-        return ProviderDefinedType(name, properties)
\ No newline at end of file
+        fields = r.read_object(b)
+        return ProviderDefinedType(name, fields)
\ No newline at end of file
diff --git 
a/gremlin-python/src/main/python/tests/unit/structure/io/test_graphbinaryV4.py 
b/gremlin-python/src/main/python/tests/unit/structure/io/test_graphbinaryV4.py
index 21b9cf7173..f7c8c7aa51 100644
--- 
a/gremlin-python/src/main/python/tests/unit/structure/io/test_graphbinaryV4.py
+++ 
b/gremlin-python/src/main/python/tests/unit/structure/io/test_graphbinaryV4.py
@@ -322,19 +322,19 @@ class TestGraphBinaryV4(object):
         result = 
self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(pdt))
         assert isinstance(result, ProviderDefinedType)
         assert result.name == 'Point'
-        assert result.properties == {'x': 1, 'y': 2}
+        assert result.fields == {'x': 1, 'y': 2}
 
     def test_provider_defined_type_nested(self):
         inner = ProviderDefinedType('Address', {'street': 'Main'})
         outer = ProviderDefinedType('Person', {'name': 'Alice', 'address': 
inner})
         result = 
self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(outer))
         assert result.name == 'Person'
-        assert result.properties['name'] == 'Alice'
-        assert isinstance(result.properties['address'], ProviderDefinedType)
-        assert result.properties['address'].name == 'Address'
+        assert result.fields['name'] == 'Alice'
+        assert isinstance(result.fields['address'], ProviderDefinedType)
+        assert result.fields['address'].name == 'Address'
 
     def test_provider_defined_type_null_field(self):
         pdt = ProviderDefinedType('NullableType', {'value': None, 'name': 
'test'})
         result = 
self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(pdt))
-        assert result.properties['value'] is None
-        assert result.properties['name'] == 'test'
+        assert result.fields['value'] is None
+        assert result.fields['name'] == 'test'
diff --git 
a/gremlin-python/src/main/python/tests/unit/structure/io/test_provider_defined_type.py
 
b/gremlin-python/src/main/python/tests/unit/structure/io/test_provider_defined_type.py
index 32deaa9840..b97b9905d8 100644
--- 
a/gremlin-python/src/main/python/tests/unit/structure/io/test_provider_defined_type.py
+++ 
b/gremlin-python/src/main/python/tests/unit/structure/io/test_provider_defined_type.py
@@ -105,7 +105,7 @@ class TestProviderDefinedTypeRegistry(object):
 class TestProviderDefinedTypeRegistryBuild(object):
 
     def test_build_returns_registry_with_no_entry_points(self):
-        registry = ProviderDefinedTypeRegistry.build()
+        registry = ProviderDefinedTypeRegistry.create()
         assert isinstance(registry, ProviderDefinedTypeRegistry)
 
     def test_build_loads_entry_point(self):
@@ -122,7 +122,7 @@ class TestProviderDefinedTypeRegistryBuild(object):
             else:
                 mock_entry_points.return_value = {'tinkerpop.pdt': [mock_ep]}
 
-            registry = ProviderDefinedTypeRegistry.build()
+            registry = ProviderDefinedTypeRegistry.create()
             assert "com.mock.Type" in registry._adapters_by_name
 
     def test_build_handles_failing_entry_point(self):
@@ -139,7 +139,7 @@ class TestProviderDefinedTypeRegistryBuild(object):
             else:
                 mock_entry_points.return_value = {'tinkerpop.pdt': [mock_ep]}
 
-            registry = ProviderDefinedTypeRegistry.build()
+            registry = ProviderDefinedTypeRegistry.create()
             assert isinstance(registry, ProviderDefinedTypeRegistry)
             assert len(registry._adapters_by_name) == 0
 
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 03fafbd3f1..3f7f61dd30 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
@@ -1287,8 +1287,8 @@ public class GremlinDriverIntegrateTest extends 
AbstractGremlinServerIntegration
             assertTrue(result instanceof ProviderDefinedType);
             final ProviderDefinedType r = (ProviderDefinedType) result;
             assertEquals("TestPoint", r.getName());
-            assertEquals(1, r.getProperties().get("x"));
-            assertEquals(2, r.getProperties().get("y"));
+            assertEquals(1, r.getFields().get("x"));
+            assertEquals(2, r.getFields().get("y"));
         } finally {
             cluster.close();
         }
@@ -1386,8 +1386,8 @@ public class GremlinDriverIntegrateTest extends 
AbstractGremlinServerIntegration
                     value instanceof ProviderDefinedType);
             final ProviderDefinedType pdt = (ProviderDefinedType) value;
             assertEquals("Point", pdt.getName());
-            assertEquals(3, pdt.getProperties().get("x"));
-            assertEquals(4, pdt.getProperties().get("y"));
+            assertEquals(3, pdt.getFields().get("x"));
+            assertEquals(4, pdt.getFields().get("y"));
         } finally {
             // cleanup
             client.submit("g.V().hasLabel('location').drop().iterate()", 
groovyRequestOptions).all().get();
@@ -1407,13 +1407,13 @@ public class GremlinDriverIntegrateTest extends 
AbstractGremlinServerIntegration
         // so the adapter's type name matches the server type name "Point".
         @Override public String typeName() { return "Point"; }
         @Override public Class<TestPoint> targetClass() { return 
TestPoint.class; }
-        @Override public Map<String, Object> toProperties(final TestPoint obj) 
{
+        @Override public Map<String, Object> toFields(final TestPoint obj) {
             final Map<String, Object> m = new HashMap<>();
             m.put("x", obj.x);
             m.put("y", obj.y);
             return m;
         }
-        @Override public TestPoint fromProperties(final Map<String, Object> 
props) {
+        @Override public TestPoint fromFields(final Map<String, Object> props) 
{
             return new TestPoint(((Number) props.get("x")).intValue(), 
((Number) props.get("y")).intValue());
         }
     }
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
index 28a81731e3..746184fab4 100644
--- 
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
@@ -278,8 +278,8 @@ public class GremlinServerSerializationIntegrateTest 
extends AbstractGremlinServ
         assertEquals(1, results.size());
         final ProviderDefinedType pdt = (ProviderDefinedType) 
results.get(0).getObject();
         assertEquals("Point", pdt.getName());
-        assertEquals(1, pdt.getProperties().get("x"));
-        assertEquals(2, pdt.getProperties().get("y"));
+        assertEquals(1, pdt.getFields().get("x"));
+        assertEquals(2, pdt.getFields().get("y"));
     }
 
     @Test
@@ -291,13 +291,13 @@ public class GremlinServerSerializationIntegrateTest 
extends AbstractGremlinServ
         assertEquals(1, results.size());
         final ProviderDefinedType person = (ProviderDefinedType) 
results.get(0).getObject();
         assertEquals("Person", person.getName());
-        assertEquals("Alice", person.getProperties().get("name"));
-        assertEquals(30, person.getProperties().get("age"));
+        assertEquals("Alice", person.getFields().get("name"));
+        assertEquals(30, person.getFields().get("age"));
 
-        final ProviderDefinedType address = (ProviderDefinedType) 
person.getProperties().get("address");
+        final ProviderDefinedType address = (ProviderDefinedType) 
person.getFields().get("address");
         assertEquals("Address", address.getName());
-        assertEquals("123 Main St", address.getProperties().get("street"));
-        assertEquals("Springfield", address.getProperties().get("city"));
+        assertEquals("123 Main St", address.getFields().get("street"));
+        assertEquals("Springfield", address.getFields().get("city"));
     }
 
     @Test
@@ -311,13 +311,13 @@ public class GremlinServerSerializationIntegrateTest 
extends AbstractGremlinServ
 
         final ProviderDefinedType p1 = (ProviderDefinedType) list.get(0);
         assertEquals("Point", p1.getName());
-        assertEquals(1, p1.getProperties().get("x"));
-        assertEquals(2, p1.getProperties().get("y"));
+        assertEquals(1, p1.getFields().get("x"));
+        assertEquals(2, p1.getFields().get("y"));
 
         final ProviderDefinedType p2 = (ProviderDefinedType) list.get(1);
         assertEquals("Point", p2.getName());
-        assertEquals(3, p2.getProperties().get("x"));
-        assertEquals(4, p2.getProperties().get("y"));
+        assertEquals(3, p2.getFields().get("x"));
+        assertEquals(4, p2.getFields().get("y"));
     }
 
     @Test
diff --git 
a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphBinaryMessageSerializerV4.java
 
b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphBinaryMessageSerializerV4.java
index 795712ff76..9204118184 100644
--- 
a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphBinaryMessageSerializerV4.java
+++ 
b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphBinaryMessageSerializerV4.java
@@ -55,18 +55,15 @@ public class GraphBinaryMessageSerializerV4 extends 
AbstractMessageSerializer<Gr
     private static final String MIME_TYPE = SerTokens.MIME_GRAPHBINARY_V4;
 
     /**
-     * Creates a new instance of the message serializer using the default type 
serializers.
+     * Creates a new instance of the message serializer using the default type 
serializers and
+     * an SPI-discovered {@link ProviderDefinedTypeRegistry} for automatic PDT 
hydration.
      */
     public GraphBinaryMessageSerializerV4() {
-        this(TypeSerializerRegistry.INSTANCE);
+        this(TypeSerializerRegistry.INSTANCE, 
ProviderDefinedTypeRegistry.create());
     }
 
     public GraphBinaryMessageSerializerV4(final TypeSerializerRegistry 
registry) {
-        reader = new GraphBinaryReader(registry);
-        writer = new GraphBinaryWriter(registry);
-        mapper = new GraphBinaryMapper(writer, reader);
-
-        requestSerializer = new RequestMessageSerializer();
+        this(registry, ProviderDefinedTypeRegistry.create());
     }
 
     public GraphBinaryMessageSerializerV4(final TypeSerializerRegistry 
registry, final ProviderDefinedTypeRegistry pdtRegistry) {
@@ -104,7 +101,7 @@ public class GraphBinaryMessageSerializerV4 extends 
AbstractMessageSerializer<Gr
         }
 
         final TypeSerializerRegistry registry = builder.create();
-        reader = new GraphBinaryReader(registry);
+        reader = new GraphBinaryReader(registry, 
ProviderDefinedTypeRegistry.create());
         writer = new GraphBinaryWriter(registry);
 
         requestSerializer = new RequestMessageSerializer();
diff --git 
a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryPdtSpiAutoWiringTest.java
 
b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryPdtSpiAutoWiringTest.java
new file mode 100644
index 0000000000..b356b82776
--- /dev/null
+++ 
b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryPdtSpiAutoWiringTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+import org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry;
+import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedType;
+import 
org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeRegistry;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV4;
+import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Validates that the default {@link GraphBinaryMessageSerializerV4} 
auto-wires SPI-discovered
+ * {@link 
org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter} 
implementations
+ * for hydration without any user configuration.
+ */
+public class GraphBinaryPdtSpiAutoWiringTest {
+
+    private final ByteBufAllocator allocator = ByteBufAllocator.DEFAULT;
+
+    @Test
+    public void shouldAutoHydrateSpiDiscoveredAdapterWithDefaultSerializer() 
throws SerializationException {
+        // The default no-arg constructor should pick up TestPointAdapter via 
SPI
+        final GraphBinaryMessageSerializerV4 serializer = new 
GraphBinaryMessageSerializerV4();
+
+        // Build a response containing a raw ProviderDefinedType matching the 
test adapter's typeName
+        final Map<String, Object> fields = new LinkedHashMap<>();
+        fields.put("x", 10);
+        fields.put("y", 20);
+        final ProviderDefinedType pdt = new ProviderDefinedType("test.Point", 
fields);
+
+        final ResponseMessage response = ResponseMessage.build()
+                .result(Collections.singletonList(pdt))
+                .create();
+
+        // Serialize and deserialize — the reader should hydrate the PDT into 
TestPoint
+        final ByteBuf buffer = serializer.writeHeader(response, allocator);
+        try {
+            final ResponseMessage deserialized = serializer.readChunk(buffer, 
true);
+            assertNotNull(deserialized.getResult().getData());
+            assertEquals(1, deserialized.getResult().getData().size());
+
+            final Object result = deserialized.getResult().getData().get(0);
+            assertTrue("Expected hydrated TestPoint but got: " + 
result.getClass().getName(),
+                    result instanceof TestPointAdapter.TestPoint);
+
+            final TestPointAdapter.TestPoint point = 
(TestPointAdapter.TestPoint) result;
+            assertEquals(10, point.x);
+            assertEquals(20, point.y);
+        } finally {
+            buffer.release();
+        }
+    }
+
+    @Test
+    public void shouldAutoHydrateSpiDiscoveredAdapterAfterConfigure() throws 
SerializationException {
+        // Verify configure() also includes the SPI registry
+        final GraphBinaryMessageSerializerV4 serializer = new 
GraphBinaryMessageSerializerV4();
+        serializer.configure(Collections.emptyMap(), Collections.emptyMap());
+
+        final Map<String, Object> fields = new LinkedHashMap<>();
+        fields.put("x", 5);
+        fields.put("y", 15);
+        final ProviderDefinedType pdt = new ProviderDefinedType("test.Point", 
fields);
+
+        final ResponseMessage response = ResponseMessage.build()
+                .result(Collections.singletonList(pdt))
+                .create();
+
+        final ByteBuf buffer = serializer.writeHeader(response, allocator);
+        try {
+            final ResponseMessage deserialized = serializer.readChunk(buffer, 
true);
+            final Object result = deserialized.getResult().getData().get(0);
+            assertTrue("Expected hydrated TestPoint after configure()", result 
instanceof TestPointAdapter.TestPoint);
+        } finally {
+            buffer.release();
+        }
+    }
+
+    @Test
+    public void shouldUseExplicitPdtRegistryOverSpiDefault() throws 
SerializationException {
+        // An empty registry should NOT hydrate since it has no adapters 
registered
+        final ProviderDefinedTypeRegistry emptyRegistry = 
ProviderDefinedTypeRegistry.empty();
+        final GraphBinaryMessageSerializerV4 serializer = new 
GraphBinaryMessageSerializerV4(
+                TypeSerializerRegistry.INSTANCE, emptyRegistry);
+
+        final Map<String, Object> fields = new LinkedHashMap<>();
+        fields.put("x", 1);
+        fields.put("y", 2);
+        final ProviderDefinedType pdt = new ProviderDefinedType("test.Point", 
fields);
+
+        final ResponseMessage response = ResponseMessage.build()
+                .result(Collections.singletonList(pdt))
+                .create();
+
+        final ByteBuf buffer = serializer.writeHeader(response, allocator);
+        try {
+            final ResponseMessage deserialized = serializer.readChunk(buffer, 
true);
+            final Object result = deserialized.getResult().getData().get(0);
+            // With empty registry, should remain as raw ProviderDefinedType 
(no hydration)
+            assertTrue("Expected raw ProviderDefinedType with explicit empty 
registry but got: " + result.getClass().getName(),
+                    result instanceof ProviderDefinedType);
+        } finally {
+            buffer.release();
+        }
+    }
+}
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/binary/GraphBinaryWriterPdtTest.java
 
b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryWriterPdtTest.java
similarity index 77%
rename from 
gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/binary/GraphBinaryWriterPdtTest.java
rename to 
gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryWriterPdtTest.java
index 863e2559da..2a3fa78d4f 100644
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/binary/GraphBinaryWriterPdtTest.java
+++ 
b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryWriterPdtTest.java
@@ -16,11 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.structure.io.binary;
+package org.apache.tinkerpop.gremlin.util.ser.binary;
 
+import io.netty.buffer.ByteBufAllocator;
 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.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefined;
 import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedType;
+import org.apache.tinkerpop.gremlin.util.ser.NettyBufferFactory;
 import org.junit.Test;
 
 import java.io.IOException;
@@ -35,6 +39,8 @@ public class GraphBinaryWriterPdtTest {
 
     private static final GraphBinaryReader reader = new GraphBinaryReader();
     private static final GraphBinaryWriter writer = new GraphBinaryWriter();
+    private static final ByteBufAllocator allocator = ByteBufAllocator.DEFAULT;
+    private static final NettyBufferFactory bufferFactory = new 
NettyBufferFactory();
 
     @ProviderDefined
     static class TestPoint {
@@ -53,19 +59,19 @@ public class GraphBinaryWriterPdtTest {
 
     @Test
     public void shouldAutoConvertAnnotatedObjectToPdt() throws IOException {
-        final Buffer buffer = HeapBuffer.allocate(1024);
+        final Buffer buffer = bufferFactory.create(allocator.buffer());
         writer.write(new TestPoint(1, 2), buffer);
         buffer.readerIndex(0);
 
         final ProviderDefinedType result = reader.read(buffer);
         assertEquals("TestPoint", result.getName());
-        assertEquals(1, result.getProperties().get("x"));
-        assertEquals(2, result.getProperties().get("y"));
+        assertEquals(1, result.getFields().get("x"));
+        assertEquals(2, result.getFields().get("y"));
     }
 
     @Test
     public void shouldThrowActionableMessageForUnannotatedType() {
-        final Buffer buffer = HeapBuffer.allocate(1024);
+        final Buffer buffer = bufferFactory.create(allocator.buffer());
         final IOException ex = assertThrows(IOException.class, () -> 
writer.write(new UnannotatedType(), buffer));
         assertTrue(ex.getMessage().contains("@ProviderDefined"));
         assertTrue(ex.getMessage().contains("UnannotatedType"));
@@ -78,7 +84,7 @@ public class GraphBinaryWriterPdtTest {
         props.put("y", 2);
         final ProviderDefinedType pdt = new ProviderDefinedType("TestPoint", 
props);
 
-        final Buffer buffer = HeapBuffer.allocate(1024);
+        final Buffer buffer = bufferFactory.create(allocator.buffer());
         writer.write(pdt, buffer);
         buffer.readerIndex(0);
 
diff --git 
a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/TestPointAdapter.java
 
b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/TestPointAdapter.java
new file mode 100644
index 0000000000..6a352f274c
--- /dev/null
+++ 
b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/TestPointAdapter.java
@@ -0,0 +1,63 @@
+/*
+ * 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 
org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Test-only adapter registered via META-INF/services for SPI auto-wiring 
validation.
+ */
+public class TestPointAdapter implements 
ProviderDefinedTypeAdapter<TestPointAdapter.TestPoint> {
+
+    public static class TestPoint {
+        public final int x;
+        public final int y;
+
+        public TestPoint(final int x, final int y) {
+            this.x = x;
+            this.y = y;
+        }
+    }
+
+    @Override
+    public String typeName() {
+        return "test.Point";
+    }
+
+    @Override
+    public Class<TestPoint> targetClass() {
+        return TestPoint.class;
+    }
+
+    @Override
+    public Map<String, Object> toFields(final TestPoint obj) {
+        final Map<String, Object> fields = new LinkedHashMap<>();
+        fields.put("x", obj.x);
+        fields.put("y", obj.y);
+        return fields;
+    }
+
+    @Override
+    public TestPoint fromFields(final Map<String, Object> fields) {
+        return new TestPoint(((Number) fields.get("x")).intValue(), ((Number) 
fields.get("y")).intValue());
+    }
+}
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ProviderDefinedTypeSerializerTest.java
 
b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/ProviderDefinedTypeSerializerTest.java
similarity index 89%
rename from 
gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ProviderDefinedTypeSerializerTest.java
rename to 
gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/ProviderDefinedTypeSerializerTest.java
index 76f373609d..822a835f3b 100644
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ProviderDefinedTypeSerializerTest.java
+++ 
b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/ProviderDefinedTypeSerializerTest.java
@@ -16,15 +16,17 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tinkerpop.gremlin.structure.io.binary.types;
+package org.apache.tinkerpop.gremlin.util.ser.binary.types;
 
+import io.netty.buffer.ByteBufAllocator;
 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.apache.tinkerpop.gremlin.structure.io.binary.HeapBuffer;
+import org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry;
 import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedType;
 import 
org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter;
 import 
org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeRegistry;
+import org.apache.tinkerpop.gremlin.util.ser.NettyBufferFactory;
 import org.junit.Test;
 
 import java.io.IOException;
@@ -42,9 +44,11 @@ public class ProviderDefinedTypeSerializerTest {
 
     private static final GraphBinaryReader reader = new GraphBinaryReader();
     private static final GraphBinaryWriter writer = new GraphBinaryWriter();
+    private static final ByteBufAllocator allocator = ByteBufAllocator.DEFAULT;
+    private static final NettyBufferFactory bufferFactory = new 
NettyBufferFactory();
 
     private Buffer writeAndRead(final Object value) throws IOException {
-        final Buffer buffer = HeapBuffer.allocate(1024);
+        final Buffer buffer = bufferFactory.create(allocator.buffer());
         writer.write(value, buffer);
         buffer.readerIndex(0);
         return buffer;
@@ -120,8 +124,7 @@ public class ProviderDefinedTypeSerializerTest {
 
     @Test(expected = IOException.class)
     public void shouldThrowOnEmptyNameDuringRead() throws IOException {
-        // Manually write a PDT with empty name to trigger the validation
-        final Buffer buffer = HeapBuffer.allocate(256);
+        final Buffer buffer = bufferFactory.create(allocator.buffer());
         // Write type code for COMPOSITE_PDT
         buffer.writeByte(0xF0);
         // Write value_flag = 0 (not null)
@@ -141,7 +144,7 @@ public class ProviderDefinedTypeSerializerTest {
 
     @Test(expected = IOException.class)
     public void shouldThrowOnNonStringKeyInPropertiesMap() throws IOException {
-        final Buffer buffer = HeapBuffer.allocate(256);
+        final Buffer buffer = bufferFactory.create(allocator.buffer());
         // Write type code for COMPOSITE_PDT (0xF0), value_flag 0
         buffer.writeByte(0xF0);
         buffer.writeByte(0x00);
@@ -170,7 +173,7 @@ public class ProviderDefinedTypeSerializerTest {
 
     @Test
     public void shouldHandleNullPdt() throws IOException {
-        final Buffer buffer = HeapBuffer.allocate(64);
+        final Buffer buffer = bufferFactory.create(allocator.buffer());
         writer.write(null, buffer);
         buffer.readerIndex(0);
         final Object result = reader.read(buffer);
@@ -188,18 +191,18 @@ public class ProviderDefinedTypeSerializerTest {
             public Class<Map<String, Object>> targetClass() { return (Class) 
Map.class; }
 
             @Override
-            public Map<String, Object> fromProperties(final Map<String, 
Object> properties) {
+            public Map<String, Object> fromFields(final Map<String, Object> 
properties) {
                 final Map<String, Object> result = new 
LinkedHashMap<>(properties);
                 result.put("hydrated", true);
                 return result;
             }
 
             @Override
-            public Map<String, Object> toProperties(final Map<String, Object> 
value) { return value; }
+            public Map<String, Object> toFields(final Map<String, Object> 
value) { return value; }
         });
 
         final GraphBinaryReader hydratingReader = new GraphBinaryReader(
-                
org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry.INSTANCE,
 pdtRegistry);
+                TypeSerializerRegistry.INSTANCE, pdtRegistry);
 
         final Map<String, Object> props = new LinkedHashMap<>();
         props.put("x", 1);
diff --git 
a/gremlin-util/src/test/resources/META-INF/services/org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter
 
b/gremlin-util/src/test/resources/META-INF/services/org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter
new file mode 100644
index 0000000000..408bc7aa62
--- /dev/null
+++ 
b/gremlin-util/src/test/resources/META-INF/services/org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter
@@ -0,0 +1 @@
+org.apache.tinkerpop.gremlin.util.ser.binary.TestPointAdapter

Reply via email to