You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2023/07/11 15:05:06 UTC
[tinkerpop] 01/02: TINKERPOP-2963 Changed sparse to untyped for GraphSON
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 14f2d31b5ebc7cedd50173f746cf8aaa95dfaa0e
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Tue Jul 11 10:22:41 2023 -0400
TINKERPOP-2963 Changed sparse to untyped for GraphSON
Brought back GraphSON 2 untyped for consistency sake and to setup for the same with GraphSON 3. CTR
---
CHANGELOG.asciidoc | 3 +-
docs/src/dev/io/graphson.asciidoc | 39 +++-
docs/src/reference/gremlin-applications.asciidoc | 27 ++-
docs/src/upgrade/release-3.6.x.asciidoc | 18 ++
.../console/jsr223/DriverGremlinPlugin.java | 8 +-
.../gremlin/driver/MessageSerializer.java | 9 +-
.../ser/GraphSONMessageSerializerGremlinV1d0.java | 2 +-
.../driver/ser/GraphSONMessageSerializerV1d0.java | 7 +-
.../driver/ser/GraphSONMessageSerializerV2d0.java | 10 +-
...a => GraphSONUntypedMessageSerializerV1d0.java} | 13 +-
...a => GraphSONUntypedMessageSerializerV2d0.java} | 24 +-
.../tinkerpop/gremlin/driver/ser/SerTokens.java | 5 +-
.../tinkerpop/gremlin/driver/ser/Serializers.java | 30 ++-
.../ser/GraphSONMessageSerializerV2d0Test.java | 22 +-
... GraphSONUntypedMessageSerializerV1d0Test.java} | 246 ++++++---------------
.../server/GremlinServerHttpIntegrateTest.java | 47 ++--
16 files changed, 257 insertions(+), 253 deletions(-)
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 3e0f0848d7..3ab6d2ddd9 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -28,7 +28,8 @@ This release also includes changes from <<release-3-5-7, 3.5.7>>.
* Added `text/plain` MIME type to the HTTP endpoint to return a Gremlin Console-like representation of the data.
* Added GraphBinary serialization option to the HTTP endpoint.
* Fixed bug with `fail` step not working with a `VertexProgram` running on the server.
-* Introduced new mime-type `application/vnd.gremlin-v1.0+json;sparse=true` to allow direct specification of GraphSON 1.0 without types.
+* Introduced mime type `application/vnd.gremlin-v1.0+json;typed=false` to allow direct specification of GraphSON 1.0 without types.
+* Introduced mime type `application/vnd.gremlin-v2.0+json;typed=false` to allow direct specification of GraphSON 2.0 without types.
[[release-3-6-4]]
=== TinkerPop 3.6.4 (Release Date: May 12, 2023)
diff --git a/docs/src/dev/io/graphson.asciidoc b/docs/src/dev/io/graphson.asciidoc
index f0aa50d96c..7beb961c01 100644
--- a/docs/src/dev/io/graphson.asciidoc
+++ b/docs/src/dev/io/graphson.asciidoc
@@ -435,13 +435,27 @@ the basis for the format.
The following sections discuss the GraphSON object serialization format as available in each version of GraphSON. Core
to understanding these sections is to understand that GraphSON can be produced with and without types being embedded
-in the output. Without embedded types, the type system is restricted to standard JSON types of Object, List, String,
-Number, Boolean and that will lead to "lossyness" in the format (i.e. a float will be interpreted as double).
+in the output. Without embedded types, the type system is restricted to standard JSON types of `Object`, `List`,
+`String`, `Number`, `Boolean` and that will lead to "lossyness" in the format (i.e. a float will be interpreted as
+double). It is also worth considering that choosing a GraphSON format without embedded types may also restrict the
+type of results that can be obtained. For example, `g.V().groupCount()` returns a format with a `Map`. That's fine
+for GraphSON, but the key in that `Map` is a complex object (i.e. a `Vertex`) and as such is not compatible with JSON
+itself which can only support `String` keys.
+
+WARNING: The `application/json` mime type is shared with all versions of GraphSON and their variations and does not
+reflect a particular one. Servers will return the GraphSON version and variation that this mime type is configured for
+and it could be different (or change) from server to server. When building applications, it is recommended that the
+mime type is made explicit on requests to avoid breaking changes or unexpected results.
[[graphson-1d0]]
== Version 1.0
-Version 1.0 of GraphSON was released with TinkerPop 3.0.0. When types are embedded, GraphSON uses the standard
+Version 1.0 of GraphSON was released with TinkerPop 3.0.0. It is referred to by the following mime types:
+
+* `application/vnd.gremlin-v1.0+json` - types embedded
+* `application/vnd.gremlin-v1.0+json;sparse=true` - no types embedded
+
+When types are embedded, GraphSON uses the standard
link:https://github.com/FasterXML/jackson-databind[Jackson] type embedding approach that writes the full Java class
name into a "@class" field in the JSON. While this approach isn't especially language agnostic it does at least give
some hint as to what the expected type is.
@@ -1138,14 +1152,15 @@ link:https://github.com/FasterXML/jackson-databind[Jackson] (a JVM library) and
types. While the <<graphson-1d0,GraphSON 1.0>> section focused on GraphSON without embedded types, GraphSON 2.0 will
do the opposite as embedded types is the expected manner in which non-JVM languages will interact with TinkerPop.
-With GraphSON 2.0, there are essentially two type formats:
+GraphSON 2.0 is referred to by the following mime types:
-* A non-typed value which is assumed the type implied by JSON. These non-types are limited to `String`, `Boolean`,
-`Map` and `Collection`.
-* All other values are typed by way of a "complex object" that defines a `@typeId` and `@value`. The `@typeId` is
-composed of two parts: a namespace and a type name, in the format "namespace:typename". A namespace allows TinkerPop
-providers and users to categorize custom types that they may implement and avoid collision with existing TinkerPop
-types. By default, TinkerPop types will have the namespace "g" (or "gx" for "extended" types).
+* `application/vnd.gremlin-v2.0+json` - All other values are typed by way of a "complex object" that defines a
+`@typeId` and `@value`. The `@typeId` is composed of two parts: a namespace and a type name, in the format
+"namespace:typename". A namespace allows TinkerPop providers and users to categorize custom types that they may
+implement and avoid collision with existing TinkerPop types. By default, TinkerPop types will have the namespace "g"
+(or "gx" for "extended" types).
+* `application/vnd.gremlin-v2.0+json;sparse=true` - A non-typed value which is assumed the type implied by JSON.
+These non-types are limited to `String`, `Boolean`, `Map` and `Collection`.
=== Core
@@ -3836,8 +3851,8 @@ The following example is a `ZoneOffset` of three hours, six minutes, and nine se
[[graphson-3d0]]
== Version 3.0
-Version 3.0 of GraphSON was first introduced on TinkerPop 3.3.0 and is the default format when not specified as of this
-version. It is quite similar to GraphSON 2.0 and in most cases will appear compatible to the eye, however there are
+Version 3.0 of GraphSON was first introduced on TinkerPop 3.3.0 and is represented by the `application/vnd.graphbinary-v3.0`
+mime type. It is quite similar to GraphSON 2.0 and in most cases will appear compatible to the eye, however there are
some critical differences:
* GraphSON 3.0 does not have an option to be typeless. Types are always embedded except for strings and boolean values
diff --git a/docs/src/reference/gremlin-applications.asciidoc b/docs/src/reference/gremlin-applications.asciidoc
index c46b2dca13..4a7dee4870 100644
--- a/docs/src/reference/gremlin-applications.asciidoc
+++ b/docs/src/reference/gremlin-applications.asciidoc
@@ -1132,12 +1132,37 @@ some serializers have additional configuration options as defined by the `serial
available and/or expected keys are dependent on the serializer being used. Gremlin Server comes packaged with two
different serializers: GraphSON and GraphBinary.
+WARNING: Irrespective of the serialization format chosen, it is highly recommended that the serialization format is
+specified explicitly. For example, prefer `application/vnd.gremlin-v3.0+json` to `application/json`. Use of the drivers
+tend to take care of this issue internally, but for all other mechanisms it is best to ensure the `Accept` type is
+defined this way to avoid possible breaking changes or unexpected results, as defaults may vary from server to server.
+
+WARNING: When connecting with drivers, never try to specify a serialization format that does not have embedded types.
+The drivers are designed to use that type information to properly produce results in the programming language's type
+system and may not function correctly without it. Generally speaking, `GraphBinary` is always the best choice for the
+drivers.
+
===== GraphSON
The GraphSON serializer produces human readable output in JSON format and is a good configuration choice for those
trying to use TinkerPop from non-JVM languages. JSON obviously has wide support across virtually all major
programming languages and can be consumed by a wide variety of tools. The format itself is described in the
-link:https://tinkerpop.apache.org/docs/x.y.z/dev/io/#graphson[IO Documentation].
+link:https://tinkerpop.apache.org/docs/x.y.z/dev/io/#graphson[IO Documentation]. The following table shows the
+available GraphSON serializers that can be configured:
+
+[width="100%",cols="2,2,4,4",options="header"]
+|=========================================================
+|Version |Embedded Types |Mime Type |Class
+|1.0 |yes |`application/vnd.gremlin-v1.0+json` |`GraphSONMessageSerializerGremlinV1d0`
+|1.0 |no |`application/vnd.gremlin-v1.0+json;types=false` |`GraphSONUntypedMessageSerializerV1d0`
+|2.0 |yes |`application/vnd.gremlin-v2.0+json` |`GraphSONMessageSerializerV2d0`
+|2.0 |no |`application/vnd.gremlin-v2.0+json;types=false` |`GraphSONUntypedMessageSerializerV2d0`
+|3.0 |yes |`application/vnd.gremlin-v3.0+json` |`GraphSONMessageSerializerV3d0`
+|=========================================================
+
+The above serializer classes can be found in the `org.apache.tinkerpop.gremlin.driver.ser` package of `gremlin-driver`.
+
+Configuring GraphSON in the Gremlin Server configuration looks like this:
[source,yaml]
----
diff --git a/docs/src/upgrade/release-3.6.x.asciidoc b/docs/src/upgrade/release-3.6.x.asciidoc
index d54ad7a38c..db14ee0ce8 100644
--- a/docs/src/upgrade/release-3.6.x.asciidoc
+++ b/docs/src/upgrade/release-3.6.x.asciidoc
@@ -48,6 +48,24 @@ $ curl -H "Accept:text/plain" -X POST -d "{\"gremlin\":\"g.V()\"}" "http://local
See: link:https://issues.apache.org/jira/browse/TINKERPOP-2947[TINKERPOP-2947]
+==== Untyped GraphSON
+
+Prior to GraphSON 3.0, there were options to have GraphSON returned with and without types. The latter was helpful
+for getting a more simple to process JSON format that relied strictly on the JSON type system. This format was of
+course lossy in nature and not conducive for use with the language variants that were developing as the primary
+mechanism for working with Gremlin. Of course, simple HTTP never really went away and forcing the type system on
+consumers makes that route of connecting harder than it should be.
+
+With HTTP users in mind, this version brings back both versions of untyped GraphSON by adding the following mime types:
+
+* GraphSON 1.0 - `application/vnd.gremlin-v1.0+json;types=false`
+* GraphSON 2.0 - `application/vnd.gremlin-v2.0+json;types=false`
+
+Neither is configured by default in Gremlin Server, but can be added if desired by editing the Gremlin Server
+configuration file.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2965[TINKERPOP-2965]
+
== TinkerPop 3.6.4
*Release Date: May 12, 2023*
diff --git a/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverGremlinPlugin.java b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverGremlinPlugin.java
index 3eb750ec7d..44654d5390 100644
--- a/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverGremlinPlugin.java
+++ b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverGremlinPlugin.java
@@ -37,9 +37,9 @@ import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteConnection;
import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteTraversal;
import org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1;
import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV1d0;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV2d0;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0;
import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV2d0;
+import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0;
+import org.apache.tinkerpop.gremlin.driver.ser.GraphSONUntypedMessageSerializerV1d0;
import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
import org.apache.tinkerpop.gremlin.driver.ser.SerTokens;
import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
@@ -75,9 +75,9 @@ public class DriverGremlinPlugin extends AbstractGremlinPlugin {
ResponseStatus.class,
ResponseStatusCode.class,
GraphSONMessageSerializerGremlinV1d0.class,
- GraphSONMessageSerializerGremlinV2d0.class,
- GraphSONMessageSerializerV1d0.class,
+ GraphSONUntypedMessageSerializerV1d0.class,
GraphSONMessageSerializerV2d0.class,
+ GraphSONMessageSerializerV3d0.class,
GraphBinaryMessageSerializerV1.class,
MessageTextSerializer.class,
SerializationException.class,
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/MessageSerializer.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/MessageSerializer.java
index 8b21ec4314..615077b2d6 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/MessageSerializer.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/MessageSerializer.java
@@ -33,12 +33,13 @@ import java.util.Map;
import java.util.ServiceLoader;
/**
- * Serializes data to and from Gremlin Server. Typically the object being serialized or deserialized will be an item
+ * Serializes data to and from Gremlin Server. Typically, the object being serialized or deserialized will be an item
* from an {@link Iterator} as returned from the {@code ScriptEngine} or an incoming {@link RequestMessage}.
* {@link MessageSerializer} instances are instantiated to a cache via {@link ServiceLoader} and indexed based on
- * the mime types they support. If a mime type is supported more than once, the last {@link MessageSerializer}
- * instance loaded for that mime type is assigned. If a mime type is not found the default
- * {@link GraphSONMessageSerializerV1d0} is used to return the results.
+ * the mime types they support. If a mime type is supported more than once, the first {@link MessageSerializer}
+ * instance loaded for that mime type is assigned. If a mime type is not found the server default is chosen. The
+ * default may change from version to version so it is best to not rely on it when developing applications and to
+ * always be explicit in specifying the type you wish to bind to.
*
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerGremlinV1d0.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerGremlinV1d0.java
index ef9e0ef50d..f175c30cf3 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerGremlinV1d0.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerGremlinV1d0.java
@@ -52,7 +52,7 @@ public final class GraphSONMessageSerializerGremlinV1d0 extends AbstractGraphSON
@Override
public String[] mimeTypesSupported() {
- return new String[]{MIME_TYPE};
+ return new String[]{MIME_TYPE, SerTokens.MIME_JSON};
}
@Override
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV1d0.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV1d0.java
index 67f9d1298c..87e6b0cb84 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV1d0.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV1d0.java
@@ -23,7 +23,6 @@ import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
import org.apache.tinkerpop.gremlin.structure.io.graphson.TypeInfo;
import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
@@ -37,10 +36,14 @@ import java.util.UUID;
* Serialize results to JSON with version 1.0.x schema.
*
* @author Stephen Mallette (http://stephen.genoprime.com)
+ * @deprecated As of release 3.6.5, replaced by {@link GraphSONUntypedMessageSerializerV1d0}. In the future this will
+ * become what was formerly known as {@link GraphSONMessageSerializerGremlinV1d0} which makes the naming consistent
+ * for all GraphSON versions.
*/
+@Deprecated
public final class GraphSONMessageSerializerV1d0 extends AbstractGraphSONMessageSerializerV1d0 implements MessageTextSerializer<ObjectMapper> {
private static final Logger logger = LoggerFactory.getLogger(GraphSONMessageSerializerV1d0.class);
- private static final String MIME_TYPE = SerTokens.MIME_GRAPHSON_V1D0_SPARSE;
+ private static final String MIME_TYPE = SerTokens.MIME_GRAPHSON_V1D0_UNTYPED;
private static byte[] header;
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0.java
index 058a393469..ae5042d847 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0.java
@@ -21,9 +21,7 @@ package org.apache.tinkerpop.gremlin.driver.ser;
import io.netty.buffer.ByteBufAllocator;
import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONXModuleV2d0;
import org.apache.tinkerpop.gremlin.structure.io.graphson.TypeInfo;
import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
@@ -31,8 +29,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
-import java.util.Map;
-import java.util.UUID;
/**
* Serialize results to JSON with version 2.0.x schema and the extended module.
@@ -53,10 +49,8 @@ public final class GraphSONMessageSerializerV2d0 extends AbstractGraphSONMessage
}
/**
- * Creates a default GraphSONMessageSerializer.
- *
- * By default this will internally instantiate a {@link GraphSONMapper} and register
- * a {@link GremlinServerModule} and {@link GraphSONXModuleV2d0} to the mapper.
+ * Creates a default GraphSONMessageSerializer. By default this will internally instantiate a {@link GraphSONMapper}
+ * and register a {@link GremlinServerModule} and {@link GraphSONXModuleV2d0} to the mapper.
*
* @see #GraphSONMessageSerializerV2d0(GraphSONMapper.Builder)
*/
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV1d0.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONUntypedMessageSerializerV1d0.java
similarity index 91%
copy from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV1d0.java
copy to gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONUntypedMessageSerializerV1d0.java
index 67f9d1298c..a9979f0f54 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV1d0.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONUntypedMessageSerializerV1d0.java
@@ -23,7 +23,6 @@ import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
import org.apache.tinkerpop.gremlin.structure.io.graphson.TypeInfo;
import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
@@ -34,13 +33,13 @@ import java.util.Map;
import java.util.UUID;
/**
- * Serialize results to JSON with version 1.0.x schema.
+ * Serialize results to JSON with version 1.0.x schema and sparse serialization which does not embed types.
*
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
-public final class GraphSONMessageSerializerV1d0 extends AbstractGraphSONMessageSerializerV1d0 implements MessageTextSerializer<ObjectMapper> {
- private static final Logger logger = LoggerFactory.getLogger(GraphSONMessageSerializerV1d0.class);
- private static final String MIME_TYPE = SerTokens.MIME_GRAPHSON_V1D0_SPARSE;
+public final class GraphSONUntypedMessageSerializerV1d0 extends AbstractGraphSONMessageSerializerV1d0 implements MessageTextSerializer<ObjectMapper> {
+ private static final Logger logger = LoggerFactory.getLogger(GraphSONUntypedMessageSerializerV1d0.class);
+ private static final String MIME_TYPE = SerTokens.MIME_GRAPHSON_V1D0_UNTYPED;
private static byte[] header;
@@ -51,11 +50,11 @@ public final class GraphSONMessageSerializerV1d0 extends AbstractGraphSONMessage
header = buffer.array();
}
- public GraphSONMessageSerializerV1d0() {
+ public GraphSONUntypedMessageSerializerV1d0() {
super();
}
- public GraphSONMessageSerializerV1d0(final GraphSONMapper mapper) {
+ public GraphSONUntypedMessageSerializerV1d0(final GraphSONMapper mapper) {
super(mapper);
}
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONUntypedMessageSerializerV2d0.java
similarity index 85%
copy from gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0.java
copy to gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONUntypedMessageSerializerV2d0.java
index 058a393469..5d77d4a0e7 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONUntypedMessageSerializerV2d0.java
@@ -21,9 +21,7 @@ package org.apache.tinkerpop.gremlin.driver.ser;
import io.netty.buffer.ByteBufAllocator;
import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
-import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONXModuleV2d0;
import org.apache.tinkerpop.gremlin.structure.io.graphson.TypeInfo;
import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
@@ -31,17 +29,15 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
-import java.util.Map;
-import java.util.UUID;
/**
- * Serialize results to JSON with version 2.0.x schema and the extended module.
+ * Serialize results to JSON with version 2.0.x schema and the extended module without embedded types.
*
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
-public final class GraphSONMessageSerializerV2d0 extends AbstractGraphSONMessageSerializerV2d0 implements MessageTextSerializer<ObjectMapper> {
- private static final Logger logger = LoggerFactory.getLogger(GraphSONMessageSerializerV2d0.class);
- private static final String MIME_TYPE = SerTokens.MIME_GRAPHSON_V2D0;
+public final class GraphSONUntypedMessageSerializerV2d0 extends AbstractGraphSONMessageSerializerV2d0 implements MessageTextSerializer<ObjectMapper> {
+ private static final Logger logger = LoggerFactory.getLogger(GraphSONUntypedMessageSerializerV2d0.class);
+ private static final String MIME_TYPE = SerTokens.MIME_GRAPHSON_V2D0_UNTYPED;
private static byte[] header;
@@ -58,18 +54,18 @@ public final class GraphSONMessageSerializerV2d0 extends AbstractGraphSONMessage
* By default this will internally instantiate a {@link GraphSONMapper} and register
* a {@link GremlinServerModule} and {@link GraphSONXModuleV2d0} to the mapper.
*
- * @see #GraphSONMessageSerializerV2d0(GraphSONMapper.Builder)
+ * @see #GraphSONUntypedMessageSerializerV2d0(GraphSONMapper.Builder)
*/
- public GraphSONMessageSerializerV2d0() {
+ public GraphSONUntypedMessageSerializerV2d0() {
super();
}
/**
* Create a GraphSONMessageSerializer from a {@link GraphSONMapper}. Deprecated, use
- * {@link #GraphSONMessageSerializerV2d0(GraphSONMapper.Builder)} instead.
+ * {@link #GraphSONUntypedMessageSerializerV2d0(GraphSONMapper.Builder)} instead.
*/
@Deprecated
- public GraphSONMessageSerializerV2d0(final GraphSONMapper mapper) {
+ public GraphSONUntypedMessageSerializerV2d0(final GraphSONMapper mapper) {
super(mapper);
}
@@ -80,7 +76,7 @@ public final class GraphSONMessageSerializerV2d0 extends AbstractGraphSONMessage
* this method will automatically register a {@link GremlinServerModule} to the provided
* mapper.
*/
- public GraphSONMessageSerializerV2d0(final GraphSONMapper.Builder mapperBuilder) {
+ public GraphSONUntypedMessageSerializerV2d0(final GraphSONMapper.Builder mapperBuilder) {
super(mapperBuilder);
}
@@ -92,7 +88,7 @@ public final class GraphSONMessageSerializerV2d0 extends AbstractGraphSONMessage
@Override
GraphSONMapper.Builder configureBuilder(final GraphSONMapper.Builder builder) {
// already set to 2.0 in AbstractGraphSONMessageSerializerV2d0
- return builder.typeInfo(TypeInfo.PARTIAL_TYPES).addCustomModule(new GremlinServerModule());
+ return builder.typeInfo(TypeInfo.NO_TYPES).addCustomModule(new GremlinServerModule());
}
@Override
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/SerTokens.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/SerTokens.java
index a1b92d3307..0a437e395e 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/SerTokens.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/SerTokens.java
@@ -18,8 +18,6 @@
*/
package org.apache.tinkerpop.gremlin.driver.ser;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.HaltedTraverserStrategy;
-
/**
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
@@ -40,8 +38,9 @@ public final class SerTokens {
public static final String MIME_JSON = "application/json";
public static final String MIME_GRAPHSON_V1D0 = "application/vnd.gremlin-v1.0+json";
- public static final String MIME_GRAPHSON_V1D0_SPARSE = "application/vnd.gremlin-v1.0+json;sparse=true";
+ public static final String MIME_GRAPHSON_V1D0_UNTYPED = "application/vnd.gremlin-v1.0+json;types=false";
public static final String MIME_GRAPHSON_V2D0 = "application/vnd.gremlin-v2.0+json";
+ public static final String MIME_GRAPHSON_V2D0_UNTYPED = "application/vnd.gremlin-v2.0+json;types=false";
public static final String MIME_GRAPHSON_V3D0 = "application/vnd.gremlin-v3.0+json";
public static final String MIME_GRAPHBINARY_V1D0 = "application/vnd.graphbinary-v1.0";
}
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/Serializers.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/Serializers.java
index 2a635bf459..7c06ff688a 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/Serializers.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/Serializers.java
@@ -19,7 +19,6 @@
package org.apache.tinkerpop.gremlin.driver.ser;
import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.HaltedTraverserStrategy;
/**
* An enum of the default serializers.
@@ -32,9 +31,30 @@ public enum Serializers {
* GraphSON 3.0.
*/
GRAPHSON(SerTokens.MIME_JSON),
+
+ /**
+ * GraphSON 1.0 with types.
+ */
GRAPHSON_V1D0(SerTokens.MIME_GRAPHSON_V1D0),
- GRAPHSON_V1D0_SPARSE(SerTokens.MIME_GRAPHSON_V1D0_SPARSE),
+
+ /**
+ * GraphSON 2.0 without types.
+ */
+ GRAPHSON_V1D0_UNTYPED(SerTokens.MIME_GRAPHSON_V1D0_UNTYPED),
+
+ /**
+ * GraphSON 2.0 with types.
+ */
GRAPHSON_V2D0(SerTokens.MIME_GRAPHSON_V2D0),
+
+ /**
+ * GraphSON 2.0 without types.
+ */
+ GRAPHSON_V2D0_UNTYPED(SerTokens.MIME_GRAPHSON_V2D0_UNTYPED),
+
+ /**
+ * GraphSON 3.0 with types.
+ */
GRAPHSON_V3D0(SerTokens.MIME_GRAPHSON_V3D0),
GRAPHBINARY_V1D0(SerTokens.MIME_GRAPHBINARY_V1D0);
@@ -55,10 +75,12 @@ public enum Serializers {
return new GraphSONMessageSerializerV3d0();
case SerTokens.MIME_GRAPHSON_V1D0:
return new GraphSONMessageSerializerGremlinV1d0();
- case SerTokens.MIME_GRAPHSON_V1D0_SPARSE:
- return new GraphSONMessageSerializerV1d0();
+ case SerTokens.MIME_GRAPHSON_V1D0_UNTYPED:
+ return new GraphSONUntypedMessageSerializerV1d0();
case SerTokens.MIME_GRAPHSON_V2D0:
return new GraphSONMessageSerializerV2d0();
+ case SerTokens.MIME_GRAPHSON_V2D0_UNTYPED:
+ return new GraphSONUntypedMessageSerializerV2d0();
case SerTokens.MIME_GRAPHBINARY_V1D0:
return new GraphBinaryMessageSerializerV1();
default:
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0Test.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0Test.java
index 3d01af41e3..9a2d07322c 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0Test.java
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0Test.java
@@ -40,6 +40,7 @@ import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONTokens;
import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONWriter;
import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONXModuleV2d0;
+import org.apache.tinkerpop.gremlin.structure.io.graphson.TinkerPopJacksonModule;
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
@@ -51,6 +52,7 @@ import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
import org.apache.tinkerpop.shaded.jackson.databind.SerializerProvider;
import org.apache.tinkerpop.shaded.jackson.databind.module.SimpleModule;
import org.apache.tinkerpop.shaded.jackson.databind.node.NullNode;
+import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdScalarSerializer;
import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdSerializer;
import org.apache.tinkerpop.shaded.jackson.databind.util.StdDateFormat;
import org.junit.Test;
@@ -95,7 +97,7 @@ public class GraphSONMessageSerializerV2d0Test {
@Test
public void shouldConfigureIoRegistry() throws Exception {
- final GraphSONMessageSerializerV1d0 serializer = new GraphSONMessageSerializerV1d0();
+ final GraphSONMessageSerializerV2d0 serializer = new GraphSONMessageSerializerV2d0();
final Map<String, Object> config = new HashMap<String, Object>() {{
put(AbstractMessageSerializer.TOKEN_IO_REGISTRIES, Arrays.asList(ColorIoRegistry.class.getName()));
}};
@@ -107,7 +109,8 @@ public class GraphSONMessageSerializerV2d0Test {
final String results = serializer.serializeResponseAsString(toSerialize, allocator);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
- assertThat(json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA).booleanValue(), is(true));
+ assertThat(json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA).get(GraphSONTokens.VALUEPROP).booleanValue(), is(true));
+ assertEquals("java:color", json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA).get(GraphSONTokens.VALUETYPE).textValue());
}
@Test
@@ -594,15 +597,26 @@ public class GraphSONMessageSerializerV2d0Test {
}
}
- public static class ColorSimpleModule extends SimpleModule {
+ public static class ColorSimpleModule extends TinkerPopJacksonModule {
public ColorSimpleModule() {
super("color-fun");
addSerializer(Color.class, new ColorSerializer());
+ }
+ @Override
+ public Map<Class, String> getTypeDefinitions() {
+ return new HashMap<Class, String>(){{
+ put(Color.class, "color");
+ }};
+ }
+
+ @Override
+ public String getTypeNamespace() {
+ return "java";
}
}
- public static class ColorSerializer extends StdSerializer<Color> {
+ public static class ColorSerializer extends StdScalarSerializer<Color> {
public ColorSerializer() {
super(Color.class);
}
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0Test.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONUntypedMessageSerializerV1d0Test.java
similarity index 65%
copy from gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0Test.java
copy to gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONUntypedMessageSerializerV1d0Test.java
index 3d01af41e3..0affec6047 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONMessageSerializerV2d0Test.java
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/GraphSONUntypedMessageSerializerV1d0Test.java
@@ -18,10 +18,7 @@
*/
package org.apache.tinkerpop.gremlin.driver.ser;
-import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
-import io.netty.buffer.UnpooledByteBufAllocator;
-import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
@@ -33,19 +30,13 @@ import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.apache.tinkerpop.gremlin.structure.io.AbstractIoRegistry;
-import org.apache.tinkerpop.gremlin.structure.io.GraphWriter;
import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONIo;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONTokens;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONWriter;
-import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONXModuleV2d0;
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
import org.apache.tinkerpop.shaded.jackson.core.JsonGenerationException;
import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator;
-import org.apache.tinkerpop.shaded.jackson.databind.JsonMappingException;
import org.apache.tinkerpop.shaded.jackson.databind.JsonNode;
import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
import org.apache.tinkerpop.shaded.jackson.databind.SerializerProvider;
@@ -53,26 +44,23 @@ import org.apache.tinkerpop.shaded.jackson.databind.module.SimpleModule;
import org.apache.tinkerpop.shaded.jackson.databind.node.NullNode;
import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdSerializer;
import org.apache.tinkerpop.shaded.jackson.databind.util.StdDateFormat;
+import org.junit.Assert;
import org.junit.Test;
-import java.awt.Color;
-import java.io.ByteArrayOutputStream;
+import java.awt.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
-import java.util.Set;
import java.util.UUID;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
@@ -81,21 +69,17 @@ import static org.junit.Assert.fail;
*
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
-@SuppressWarnings("unchecked")
-public class GraphSONMessageSerializerV2d0Test {
+public class GraphSONUntypedMessageSerializerV1d0Test {
- public static final GraphSONMessageSerializerV2d0 SERIALIZER = new GraphSONMessageSerializerV2d0();
+ public static final GraphSONUntypedMessageSerializerV1d0 SERIALIZER = new GraphSONUntypedMessageSerializerV1d0();
private static final RequestMessage msg = RequestMessage.build("op")
.overrideRequestId(UUID.fromString("2D62161B-9544-4F39-AF44-62EC49F9A595")).create();
private static final ObjectMapper mapper = new ObjectMapper();
-
- private final UUID requestId = UUID.fromString("6457272A-4018-4538-B9AE-08DD5DDC0AA1");
- private final ResponseMessage.Builder responseMessageBuilder = ResponseMessage.build(requestId);
- private final static ByteBufAllocator allocator = UnpooledByteBufAllocator.DEFAULT;
+ private static final ByteBufAllocator allocator = ByteBufAllocator.DEFAULT;
@Test
public void shouldConfigureIoRegistry() throws Exception {
- final GraphSONMessageSerializerV1d0 serializer = new GraphSONMessageSerializerV1d0();
+ final GraphSONUntypedMessageSerializerV1d0 serializer = new GraphSONUntypedMessageSerializerV1d0();
final Map<String, Object> config = new HashMap<String, Object>() {{
put(AbstractMessageSerializer.TOKEN_IO_REGISTRIES, Arrays.asList(ColorIoRegistry.class.getName()));
}};
@@ -145,7 +129,7 @@ public class GraphSONMessageSerializerV2d0Test {
funList.add(new FunObject("x"));
funList.add(new FunObject("y"));
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(funList).create(), allocator);
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(funList.iterator()).create(), allocator);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
@@ -225,9 +209,9 @@ public class GraphSONMessageSerializerV2d0Test {
final JsonNode jsonObject = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
jsonObject.elements().forEachRemaining(e -> {
if (e.has("x"))
- assertEquals(1, e.get("x").get(GraphSONTokens.VALUEPROP).asInt());
+ assertEquals(1, e.get("x").asInt());
else if (e.has(v1.id().toString()))
- assertEquals(100, e.get(v1.id().toString()).get(GraphSONTokens.VALUEPROP).asInt());
+ assertEquals(100, e.get(v1.id().toString()).asInt());
else if (e.has(StdDateFormat.instance.format(d)))
assertEquals("test", e.get(StdDateFormat.instance.format(d)).asText());
else
@@ -255,17 +239,18 @@ public class GraphSONMessageSerializerV2d0Test {
assertNotNull(converted);
assertEquals(1, converted.size());
- final JsonNode edgeAsJson = converted.get(0).get(GraphSONTokens.VALUEPROP);
+ final JsonNode edgeAsJson = converted.get(0);
assertNotNull(edgeAsJson);
- assertEquals(((Long) e.id()).longValue(), edgeAsJson.get(GraphSONTokens.ID).get(GraphSONTokens.VALUEPROP).asLong());
- assertEquals(((Long) v1.id()).longValue(), edgeAsJson.get(GraphSONTokens.OUT).get(GraphSONTokens.VALUEPROP).asLong());
- assertEquals(((Long) v2.id()).longValue(), edgeAsJson.get(GraphSONTokens.IN).get(GraphSONTokens.VALUEPROP).asLong());
+ assertEquals(((Long) e.id()).intValue(), edgeAsJson.get(GraphSONTokens.ID).asLong()); // lossy
+ assertEquals(((Long) v1.id()).intValue(), edgeAsJson.get(GraphSONTokens.OUT).asLong());// lossy
+ assertEquals(((Long) v2.id()).intValue(), edgeAsJson.get(GraphSONTokens.IN).asLong()); // lossy
assertEquals(e.label(), edgeAsJson.get(GraphSONTokens.LABEL).asText());
+ assertEquals(GraphSONTokens.EDGE, edgeAsJson.get(GraphSONTokens.TYPE).asText());
final JsonNode properties = edgeAsJson.get(GraphSONTokens.PROPERTIES);
assertNotNull(properties);
- assertEquals(123, properties.get("abc").get(GraphSONTokens.VALUEPROP).get("value").get(GraphSONTokens.VALUEPROP).asInt());
+ assertEquals(123, properties.get("abc").asInt());
}
@Test
@@ -291,7 +276,7 @@ public class GraphSONMessageSerializerV2d0Test {
final JsonNode propertyAsJson = converted.get(0);
assertNotNull(propertyAsJson);
- assertEquals(123, propertyAsJson.get(GraphSONTokens.VALUEPROP).get("value").get(GraphSONTokens.VALUEPROP).asInt());
+ assertEquals(123, propertyAsJson.get("value").asInt());
}
@Test
@@ -320,7 +305,7 @@ public class GraphSONMessageSerializerV2d0Test {
assertNotNull(converted);
assertEquals(1, converted.size());
- final JsonNode vertexAsJson = converted.get(0).get(GraphSONTokens.VALUEPROP);
+ final JsonNode vertexAsJson = converted.get(0);
assertNotNull(vertexAsJson);
final JsonNode properties = vertexAsJson.get(GraphSONTokens.PROPERTIES);
@@ -329,18 +314,18 @@ public class GraphSONMessageSerializerV2d0Test {
final JsonNode friendProperties = properties.get("friends");
assertEquals(1, friendProperties.size());
- final JsonNode friendsProperty = friendProperties.get(0).get(GraphSONTokens.VALUEPROP).get(GraphSONTokens.VALUE);
+ final JsonNode friendsProperty = friendProperties.get(0);
assertNotNull(friendsProperty);
- assertEquals(3, friendsProperty.size());
+ assertEquals(3, friends.size());
- final String object1 = friendsProperty.get(0).asText();
+ final String object1 = friendsProperty.get(GraphSONTokens.VALUE).get(0).asText();
assertEquals("x", object1);
- final int object2 = friendsProperty.get(1).get(GraphSONTokens.VALUEPROP).asInt();
+ final int object2 = friendsProperty.get(GraphSONTokens.VALUE).get(1).asInt();
assertEquals(5, object2);
- final JsonNode object3 = friendsProperty.get(2);
- assertEquals(500, object3.get("x").get(GraphSONTokens.VALUEPROP).asInt());
+ final JsonNode object3 = friendsProperty.get(GraphSONTokens.VALUE).get(2);
+ assertEquals(500, object3.get("x").asInt());
assertEquals("some", object3.get("y").asText());
}
@@ -362,7 +347,7 @@ public class GraphSONMessageSerializerV2d0Test {
// with no embedded types the key (which is a vertex) simply serializes out to an id
// {"result":{"1":1000},"code":200,"requestId":"2d62161b-9544-4f39-af44-62ec49f9a595","type":0}
- assertEquals(1000, converted.get("1").get(GraphSONTokens.VALUEPROP).asInt());
+ assertEquals(1000, converted.get("1").asInt());
}
@Test
@@ -422,13 +407,37 @@ public class GraphSONMessageSerializerV2d0Test {
assertEquals(ResponseStatusCode.SUCCESS.getValue(), deserialized.getStatus().getCode().getValue());
assertEquals("worked", deserialized.getStatus().getMessage());
}
-
+
+ @Test
+ public void shouldDeserializeResponseMessageWithNullMessage() throws Exception {
+ final UUID id = UUID.randomUUID();
+
+ final Map<String, Object> metaData = new HashMap<>();
+ metaData.put("test", UUID.randomUUID().toString());
+ final Map<String, Object> attributes = Collections.emptyMap();
+
+ final ResponseMessage response = ResponseMessage.build(id)
+ .responseMetaData(metaData)
+ .code(ResponseStatusCode.SERVER_ERROR)
+ .result("some-result")
+ .statusAttributes(attributes)
+ // explicitly pass the null value
+ .statusMessage(null)
+ .create();
+
+ final String results = SERIALIZER.serializeResponseAsString(response, allocator);
+ final ResponseMessage deserialized = SERIALIZER.deserializeResponse(results);
+ Assert.assertNotNull(SERIALIZER.getClass().getSimpleName() + " should be able to deserialize ResponseMessage "
+ + "with null message field", deserialized);
+ }
+
@Test
- public void shouldSerializeToTreeJson() throws Exception {
+ public void shouldSerializeToJsonTree() throws Exception {
final TinkerGraph graph = TinkerFactory.createClassic();
final GraphTraversalSource g = graph.traversal();
final Tree t = g.V(1).out().properties("name").tree().next();
+
final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(t).create(), allocator);
final JsonNode json = mapper.readTree(results);
@@ -437,143 +446,30 @@ public class GraphSONMessageSerializerV2d0Test {
assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
assertNotNull(converted);
-
- //result is: tree{v1=>tree{vp['name'->'vadas']=>null, vp['name'->'lop']=>null, vp['name'->'josh']=>null}}
//check the first object and it's properties
- assertEquals(1, converted.get(GraphSONTokens.VALUEPROP)
- .get(0)
- .get(GraphSONTokens.KEY).get(GraphSONTokens.VALUEPROP)
- .get(GraphSONTokens.ID).get(GraphSONTokens.VALUEPROP).asInt());
-
- assertEquals("marko", converted.get(GraphSONTokens.VALUEPROP)
- .get(0)
- .get(GraphSONTokens.KEY).get(GraphSONTokens.VALUEPROP)
- .get(GraphSONTokens.PROPERTIES)
- .get("name")
- .get(0)
- .get(GraphSONTokens.VALUEPROP).get(GraphSONTokens.VALUE).asText());
-
- //check the leafs
- Set expectedValues = new HashSet<String>() {{
- add("vadas");
- add("lop");
- add("josh");
- }};
+ assertEquals(1, converted.get("1").get("key").get("id").asInt());
+ assertEquals("marko", converted.get("1").get("key").get("properties").get("name").get(0).get("value").asText());
- Set actualValues = new HashSet<String>();
- for (int i = 0; i < 3; i++) {
- actualValues.add(converted.get(GraphSONTokens.VALUEPROP)
- .get(0)
- .get(GraphSONTokens.VALUE).get(GraphSONTokens.VALUEPROP)
- .get(i)
- .get(GraphSONTokens.KEY).get(GraphSONTokens.VALUEPROP)
- .get(GraphSONTokens.PROPERTIES)
- .get("name")
- .get(0)
- .get(GraphSONTokens.VALUEPROP).get(GraphSONTokens.VALUE).asText());
- }
-
- assertEquals(expectedValues, actualValues);
- }
-
- @Test
- public void shouldToStringUnknownObjects() {
- GraphSONMapper gm20 = GraphSONMapper.build().version(GraphSONVersion.V2_0).create();
- GraphSONMapper gm10 = GraphSONMapper.build().version(GraphSONVersion.V1_0).create();
-
- GraphWriter writer = GraphSONWriter.build().mapper(gm20).create();
- // subsequent creations of GraphWriters and GraphSONMappers should not affect
- // each other.
- GraphWriter writer2 = GraphSONWriter.build().mapper(gm10).create();
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- try {
- writer.writeObject(baos, new FunObject("value"));
- assertEquals(baos.toString(), "\"value\"");
- } catch (Exception e) {
- fail("should have succeeded serializing the unknown object to a string");
- }
- }
-
- @Test
- public void shouldSerializeAndDeserializeRequestMessageFromObjectMapper() throws IOException {
- final ObjectMapper om = GraphSONMapper.build().version(GraphSONVersion.V2_0)
- .addCustomModule(new GraphSONMessageSerializerGremlinV2d0.GremlinServerModule())
- .create().createMapper();
-
- final Map<String, Object> requestBindings = new HashMap<>();
- requestBindings.put("x", 1);
-
- final Map<String, Object> requestAliases = new HashMap<>();
- requestAliases.put("g", "social");
-
- final RequestMessage requestMessage = RequestMessage.build("eval").processor("session").
- overrideRequestId(UUID.fromString("cb682578-9d92-4499-9ebc-5c6aa73c5397")).
- add("gremlin", "social.V(x)", "bindings", requestBindings, "language", "gremlin-groovy", "aliases", requestAliases, "session", UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).create();
-
- final String json = om.writeValueAsString(requestMessage);
- final RequestMessage readRequestMessage = om.readValue(json, RequestMessage.class);
-
- assertEquals(requestMessage.getOp(), readRequestMessage.getOp());
- assertEquals(requestMessage.getProcessor(), readRequestMessage.getProcessor());
- assertEquals(requestMessage.getRequestId(), readRequestMessage.getRequestId());
- assertEquals(requestMessage.getArgs(), readRequestMessage.getArgs());
- }
-
- @Test
- public void shouldSerializeAndDeserializeResponseMessageFromObjectMapper() throws IOException {
- final ObjectMapper om = GraphSONMapper.build().version(GraphSONVersion.V2_0)
- .addCustomModule(new GraphSONMessageSerializerGremlinV2d0.GremlinServerModule())
- .create().createMapper();
- final Graph graph = TinkerFactory.createModern();
-
- final ResponseMessage responseMessage = ResponseMessage.build(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786")).
- code(org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode.SUCCESS).
- result(Collections.singletonList(graph.vertices().next())).create();
-
- final String respJson = om.writeValueAsString(responseMessage);
- final ResponseMessage responseMessageRead = om.readValue(respJson, ResponseMessage.class);
-
- assertEquals(responseMessage.getRequestId(), responseMessageRead.getRequestId());
- assertEquals(responseMessage.getResult().getMeta(), responseMessageRead.getResult().getMeta());
- assertEquals(responseMessage.getResult().getData(), responseMessageRead.getResult().getData());
- assertEquals(responseMessage.getStatus().getAttributes(), responseMessageRead.getStatus().getAttributes());
- assertEquals(responseMessage.getStatus().getCode().getValue(), responseMessageRead.getStatus().getCode().getValue());
- assertEquals(responseMessage.getStatus().getCode().isSuccess(), responseMessageRead.getStatus().getCode().isSuccess());
- assertEquals(responseMessage.getStatus().getMessage(), responseMessageRead.getStatus().getMessage());
- }
-
- @Test
- public void shouldRegisterGremlinServerModuleAutomaticallyWithMapper() throws SerializationException {
- GraphSONMapper.Builder builder = GraphSONMapper.build().addCustomModule(GraphSONXModuleV2d0.build().create(false));
- GraphSONMessageSerializerV2d0 graphSONMessageSerializerV2d0 = new GraphSONMessageSerializerV2d0(builder);
-
- ResponseMessage rm = convert("hello", graphSONMessageSerializerV2d0);
- assertEquals(rm.getRequestId(), requestId);
- assertEquals(rm.getResult().getData(), "hello");
- }
-
-
- @Test
- @SuppressWarnings("deprecation")
- public void shouldFailOnMessageSerializerWithMapperIfNoGremlinServerModule() {
- final GraphSONMapper.Builder builder = GraphSONMapper.build().addCustomModule(GraphSONXModuleV2d0.build().create(false));
- final GraphSONMessageSerializerV2d0 graphSONMessageSerializerV2d0 = new GraphSONMessageSerializerV2d0(builder.create());
-
- try {
- convert("hello", graphSONMessageSerializerV2d0);
- fail("Serialization should have failed since no GremlinServerModule registered.");
- } catch (SerializationException e) {
- assertTrue(e.getMessage().contains("Could not find a type identifier for the class"));
- assertTrue(e.getCause() instanceof JsonMappingException);
- assertTrue(e.getCause().getCause() instanceof IllegalArgumentException);
- }
- }
-
- private ResponseMessage convert(final Object toSerialize, MessageSerializer<?> serializer) throws SerializationException {
- final ByteBuf bb = serializer.serializeResponseAsBinary(responseMessageBuilder.result(toSerialize).create(), allocator);
- return serializer.deserializeResponse(bb);
+ //check objects tree structure
+ //check Vertex property
+ assertEquals("vadas", converted.get("1")
+ .get("value")
+ .get("2")
+ .get("value")
+ .get("3").get("key").get("value").asText());
+ assertEquals("name", converted.get("1")
+ .get("value")
+ .get("2")
+ .get("value")
+ .get("3").get("key").get("label").asText());
+
+ // check subitem
+ assertEquals("lop", converted.get("1")
+ .get("value")
+ .get("3")
+ .get("key")
+ .get("properties").get("name").get(0).get("value").asText());
}
private class FunObject {
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java
index 664cb58aa8..5306490ced 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java
@@ -22,10 +22,12 @@ import org.apache.commons.lang3.RandomStringUtils;
import org.apache.http.HttpHeaders;
import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
import org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1;
-import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0;
+import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV1d0;
import org.apache.tinkerpop.gremlin.driver.Tokens;
import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV2d0;
import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0;
+import org.apache.tinkerpop.gremlin.driver.ser.GraphSONUntypedMessageSerializerV1d0;
+import org.apache.tinkerpop.gremlin.driver.ser.GraphSONUntypedMessageSerializerV2d0;
import org.apache.tinkerpop.gremlin.driver.ser.SerTokens;
import org.apache.tinkerpop.gremlin.server.auth.SimpleAuthenticator;
import org.apache.tinkerpop.gremlin.server.channel.HttpChannelizer;
@@ -95,7 +97,7 @@ public class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra
case "should200OnPOSTWithGraphSON1d0AcceptHeaderDefaultResultToJson":
settings.serializers.clear();
final Settings.SerializerSettings serializerSettingsV1 = new Settings.SerializerSettings();
- serializerSettingsV1.className = GraphSONMessageSerializerV1d0.class.getName();
+ serializerSettingsV1.className = GraphSONUntypedMessageSerializerV1d0.class.getName();
settings.serializers.add(serializerSettingsV1);
break;
case "should200OnPOSTWithGraphSON2d0AcceptHeaderDefaultResultToJson":
@@ -112,15 +114,21 @@ public class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra
break;
case "should200OnPOSTWithAnyGraphSONAcceptHeaderDefaultResultToJson":
settings.serializers.clear();
- final Settings.SerializerSettings serializerSettingsAllV1 = new Settings.SerializerSettings();
- serializerSettingsAllV1.className = GraphSONMessageSerializerV1d0.class.getName();
- settings.serializers.add(serializerSettingsAllV1);
- final Settings.SerializerSettings serializerSettingsAllV2 = new Settings.SerializerSettings();
- serializerSettingsAllV2.className = GraphSONMessageSerializerV2d0.class.getName();
- settings.serializers.add(serializerSettingsAllV2);
- final Settings.SerializerSettings serializerSettingsAllV3 = new Settings.SerializerSettings();
- serializerSettingsAllV3.className = GraphSONMessageSerializerV3d0.class.getName();
- settings.serializers.add(serializerSettingsAllV3);
+ final Settings.SerializerSettings serializerSettingsSparseV1 = new Settings.SerializerSettings();
+ serializerSettingsSparseV1.className = GraphSONUntypedMessageSerializerV1d0.class.getName();
+ settings.serializers.add(serializerSettingsSparseV1);
+ final Settings.SerializerSettings serializerSettingsTypedV1 = new Settings.SerializerSettings();
+ serializerSettingsTypedV1.className = GraphSONMessageSerializerGremlinV1d0.class.getName();
+ settings.serializers.add(serializerSettingsTypedV1);
+ final Settings.SerializerSettings serializerSettingsSparseV2 = new Settings.SerializerSettings();
+ serializerSettingsSparseV2.className = GraphSONUntypedMessageSerializerV2d0.class.getName();
+ settings.serializers.add(serializerSettingsSparseV2);
+ final Settings.SerializerSettings serializerSettingsTypedV2 = new Settings.SerializerSettings();
+ serializerSettingsTypedV2.className = GraphSONMessageSerializerV2d0.class.getName();
+ settings.serializers.add(serializerSettingsTypedV2);
+ final Settings.SerializerSettings serializerSettingsTypedV3 = new Settings.SerializerSettings();
+ serializerSettingsTypedV3.className = GraphSONMessageSerializerV3d0.class.getName();
+ settings.serializers.add(serializerSettingsTypedV3);
break;
case "should401OnGETWithNoAuthorizationHeader":
case "should401OnPOSTWithNoAuthorizationHeader":
@@ -931,12 +939,12 @@ public class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra
final HttpPost httppost1Sparse = new HttpPost(TestClientFactory.createURLString());
httppost1Sparse.setHeader(HttpHeaders.CONTENT_TYPE, SerTokens.MIME_JSON);
- httppost1Sparse.setHeader(HttpHeaders.ACCEPT, SerTokens.MIME_GRAPHSON_V1D0_SPARSE);
+ httppost1Sparse.setHeader(HttpHeaders.ACCEPT, SerTokens.MIME_GRAPHSON_V1D0_UNTYPED);
httppost1Sparse.setEntity(new StringEntity("{\"gremlin\":\"1-1\"}", Consts.UTF_8));
try (final CloseableHttpResponse response = httpclient.execute(httppost1Sparse)) {
assertEquals(200, response.getStatusLine().getStatusCode());
- assertEquals(SerTokens.MIME_GRAPHSON_V1D0_SPARSE, response.getEntity().getContentType().getValue());
+ assertEquals(SerTokens.MIME_GRAPHSON_V1D0_UNTYPED, response.getEntity().getContentType().getValue());
final String json = EntityUtils.toString(response.getEntity());
final JsonNode node = mapper.readTree(json);
assertEquals(0, node.get("result").get("data").get(0).asInt());
@@ -955,6 +963,19 @@ public class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra
assertEquals(0, node.get("result").get("data").get(0).get(GraphSONTokens.VALUEPROP).asInt());
}
+ final HttpPost httppost2Sparse = new HttpPost(TestClientFactory.createURLString());
+ httppost2Sparse.setHeader(HttpHeaders.CONTENT_TYPE, SerTokens.MIME_JSON);
+ httppost2Sparse.setHeader(HttpHeaders.ACCEPT, SerTokens.MIME_GRAPHSON_V2D0_UNTYPED);
+ httppost2Sparse.setEntity(new StringEntity("{\"gremlin\":\"1-1\"}", Consts.UTF_8));
+
+ try (final CloseableHttpResponse response = httpclient.execute(httppost2Sparse)) {
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ assertEquals(SerTokens.MIME_GRAPHSON_V2D0_UNTYPED, response.getEntity().getContentType().getValue());
+ final String json = EntityUtils.toString(response.getEntity());
+ final JsonNode node = mapper.readTree(json);
+ assertEquals(0, node.get("result").get("data").get(0).asInt());
+ }
+
final HttpPost httppost3 = new HttpPost(TestClientFactory.createURLString());
httppost3.setHeader(HttpHeaders.CONTENT_TYPE, SerTokens.MIME_JSON);
httppost3.setHeader(HttpHeaders.ACCEPT, SerTokens.MIME_GRAPHSON_V3D0);