Merge branch '3.6-dev'
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 8cea5be..4db0a9a 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -57,9 +57,11 @@
[[release-3-6-5]]
=== TinkerPop 3.6.5 (Release Date: NOT OFFICIALLY RELEASED YET)
+
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.
[[release-3-6-4]]
=== TinkerPop 3.6.4 (Release Date: May 12, 2023)
diff --git a/docs/src/recipes/olap-spark-yarn.asciidoc b/docs/src/recipes/olap-spark-yarn.asciidoc
index aeb99a2..94d2071 100644
--- a/docs/src/recipes/olap-spark-yarn.asciidoc
+++ b/docs/src/recipes/olap-spark-yarn.asciidoc
@@ -87,26 +87,46 @@
$ . bin/spark-yarn.sh
----
-[gremlin-groovy]
+[source]
----
-hadoop = System.getenv('HADOOP_HOME')
-hadoopConfDir = System.getenv('HADOOP_CONF_DIR')
-archive = 'spark-gremlin.zip'
-archivePath = "/tmp/$archive"
-['bash', '-c', "rm -f $archivePath; cd ext/spark-gremlin/lib && zip $archivePath *.jar"].execute().waitFor()
-conf = new Configurations().properties(new File('conf/hadoop/hadoop-gryo.properties'))
-conf.setProperty('spark.master', 'yarn')
-conf.setProperty('spark.submit.deployMode', 'client')
-conf.setProperty('spark.yarn.archive', "$archivePath")
-conf.setProperty('spark.yarn.appMasterEnv.CLASSPATH', "./__spark_libs__/*:$hadoopConfDir")
-conf.setProperty('spark.executor.extraClassPath', "./__spark_libs__/*:$hadoopConfDir")
-conf.setProperty('spark.driver.extraLibraryPath', "$hadoop/lib/native:$hadoop/lib/native/Linux-amd64-64")
-conf.setProperty('spark.executor.extraLibraryPath', "$hadoop/lib/native:$hadoop/lib/native/Linux-amd64-64")
-conf.setProperty('gremlin.spark.persistContext', 'true')
-hdfs.copyFromLocal('data/tinkerpop-modern.kryo', 'tinkerpop-modern.kryo')
-graph = GraphFactory.open(conf)
-g = traversal().withEmbedded(graph).withComputer(SparkGraphComputer)
-g.V().group().by(values('name')).by(both().count())
+gremlin> hadoop = System.getenv('HADOOP_HOME')
+==>/home/xiazcy/.sdkman/candidates/hadoop/current
+gremlin> hadoopConfDir = System.getenv('HADOOP_CONF_DIR')
+==>/home/xiazcy/.sdkman/candidates/hadoop/current/etc/hadoop
+gremlin> archive = 'spark-gremlin.zip'
+==>spark-gremlin.zip
+gremlin> archivePath = "/tmp/$archive"
+==>/tmp/spark-gremlin.zip
+gremlin> ['bash', '-c', "rm -f $archivePath; cd ext/spark-gremlin/lib && zip $archivePath *.jar"].execute().waitFor()
+==>0
+gremlin> conf = new Configurations().properties(new File('conf/hadoop/hadoop-gryo.properties'))
+==>org.apache.commons.configuration2.PropertiesConfiguration@6c8d8b60
+gremlin> conf.setProperty('spark.master', 'yarn')
+==>null
+gremlin> conf.setProperty('spark.submit.deployMode', 'client')
+==>null
+gremlin> conf.setProperty('spark.yarn.archive', "$archivePath")
+==>null
+gremlin> conf.setProperty('spark.yarn.appMasterEnv.CLASSPATH', "./__spark_libs__/*:$hadoopConfDir")
+==>null
+gremlin> conf.setProperty('spark.executor.extraClassPath', "./__spark_libs__/*:$hadoopConfDir")
+==>null
+gremlin> conf.setProperty('spark.driver.extraLibraryPath', "$hadoop/lib/native:$hadoop/lib/native/Linux-amd64-64")
+==>null
+gremlin> conf.setProperty('spark.executor.extraLibraryPath', "$hadoop/lib/native:$hadoop/lib/native/Linux-amd64-64")
+==>null
+gremlin> conf.setProperty('gremlin.spark.persistContext', 'true')
+==>null
+gremlin> hdfs.copyFromLocal('data/tinkerpop-modern.kryo', 'tinkerpop-modern.kryo')
+==>null
+gremlin> graph = GraphFactory.open(conf)
+==>hadoopgraph[gryoinputformat->gryooutputformat]
+gremlin> g = traversal().withEmbedded(graph).withComputer(SparkGraphComputer)
+==>graphtraversalsource[hadoopgraph[gryoinputformat->gryooutputformat], sparkgraphcomputer]
+gremlin> g.V().group().by(values('name')).by(both().count())
+[WARN] o.a.s.i.Logging - Your hostname, ubuntu-22 resolves to a loopback address: 127.0.1.1; using 10.0.2.15 instead (on interface enp0s3)
+[WARN] o.a.s.i.Logging - Set SPARK_LOCAL_IP if you need to bind to another address
+==>[ripple:1,peter:1,vadas:1,josh:3,lop:3,marko:3]
----
If you run into exceptions, you will have to dig into the logs. You can do this from the command line with
diff --git a/docs/src/reference/gremlin-applications.asciidoc b/docs/src/reference/gremlin-applications.asciidoc
index 6516c77..6d70cf3 100644
--- a/docs/src/reference/gremlin-applications.asciidoc
+++ b/docs/src/reference/gremlin-applications.asciidoc
@@ -901,6 +901,21 @@
types are preserved or to pass complex objects such as lists or maps, use `POST` which will at least support the
allowed JSON data types.
+Passing the `Accept` header with a valid MIME type will trigger the server to return the result in a particular format.
+Note that in addition to the formats available given the server's `serializers` configuration, there is also a basic
+`text/plain` format which produces a text representation of results similar to the Gremlin Console:
+
+[source,text]
+----
+$ curl -H "Accept:text/plain" -X POST -d "{\"gremlin\":\"g.V()\"}" "http://localhost:8182"
+==>v[1]
+==>v[2]
+==>v[3]
+==>v[4]
+==>v[5]
+==>v[6]
+----
+
Finally, as Gremlin Server can host multiple `ScriptEngine` instances (e.g. `gremlin-groovy`, `nashorn`), it is
possible to define the language to utilize to process the request:
diff --git a/docs/src/upgrade/release-3.6.x.asciidoc b/docs/src/upgrade/release-3.6.x.asciidoc
index e416aa2..d54ad7a 100644
--- a/docs/src/upgrade/release-3.6.x.asciidoc
+++ b/docs/src/upgrade/release-3.6.x.asciidoc
@@ -29,7 +29,24 @@
=== Upgrading for Users
+==== HTTP Plain Text
+A `text/plain` MIME type has been added to the HTTP endpoint to return Gremlin Console formatted results in plain text.
+This format can be helpful for a variety of reasons. Reading JSON formatted results can be difficult sometimes and
+`text/plain` is a more simple, readable representation for when that is helpful.
+
+[source,text]
+----
+$ curl -H "Accept:text/plain" -X POST -d "{\"gremlin\":\"g.V()\"}" "http://localhost:8182"
+==>v[1]
+==>v[2]
+==>v[3]
+==>v[4]
+==>v[5]
+==>v[6]
+----
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2947[TINKERPOP-2947]
== TinkerPop 3.6.4
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketGremlinRequestEncoder.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketGremlinRequestEncoder.java
index 042980c..05226f7 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketGremlinRequestEncoder.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketGremlinRequestEncoder.java
@@ -54,7 +54,7 @@
objects.add(new BinaryWebSocketFrame(encodedMessage));
} else {
final MessageTextSerializer<?> textSerializer = (MessageTextSerializer<?>) serializer;
- objects.add(new TextWebSocketFrame(textSerializer.serializeRequestAsString(requestMessage)));
+ objects.add(new TextWebSocketFrame(textSerializer.serializeRequestAsString(requestMessage, channelHandlerContext.alloc())));
}
} catch (Exception ex) {
throw new ResponseException(ResponseStatusCode.REQUEST_ERROR_SERIALIZATION, String.format(
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/AbstractSession.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/AbstractSession.java
index 2587bea..7c04e9e 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/AbstractSession.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/AbstractSession.java
@@ -752,7 +752,7 @@
.code(code)
.statusAttributes(statusAttributes)
.responseMetaData(responseMetaData)
- .result(aggregate).create()));
+ .result(aggregate).create(), nettyContext.alloc()));
}
} catch (Exception ex) {
logger.warn("The result [{}] in the request {} could not be serialized and returned.", aggregate, msg.getRequestId(), ex);
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/GremlinResponseFrameEncoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/GremlinResponseFrameEncoder.java
index fa70e5f..879b44f 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/GremlinResponseFrameEncoder.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/GremlinResponseFrameEncoder.java
@@ -83,9 +83,9 @@
// if the request came in on a session then the serialization must occur that same thread except
// in the case of errors for reasons described above.
if (null == session || !o.getStatus().getCode().isSuccess())
- serialized = new Frame(textSerializer.serializeResponseAsString(o));
+ serialized = new Frame(textSerializer.serializeResponseAsString(o, ctx.alloc()));
else
- serialized = new Frame(session.getExecutor().submit(() -> textSerializer.serializeResponseAsString(o)).get());
+ serialized = new Frame(session.getExecutor().submit(() -> textSerializer.serializeResponseAsString(o, ctx.alloc())).get());
objects.add(serialized);
}
@@ -101,7 +101,7 @@
objects.add(serializer.serializeResponseAsBinary(error, ctx.alloc()));
} else {
final MessageTextSerializer<?> textSerializer = (MessageTextSerializer<?>) serializer;
- objects.add(textSerializer.serializeResponseAsString(error));
+ objects.add(textSerializer.serializeResponseAsString(error, ctx.alloc()));
}
}
}
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
index 6e0217b..7eda645 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
@@ -19,12 +19,14 @@
package org.apache.tinkerpop.gremlin.server.handler;
import com.codahale.metrics.Timer;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptChecker;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.AbstractTraverser;
import org.apache.tinkerpop.gremlin.structure.Element;
import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceFactory;
import org.apache.tinkerpop.gremlin.util.Tokens;
import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
+import org.apache.tinkerpop.gremlin.server.util.TextPlainMessageSerializer;
import org.javatuples.Pair;
import org.javatuples.Quartet;
import org.slf4j.Logger;
@@ -65,10 +67,12 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -104,6 +108,11 @@
*/
private final Map<String, MessageSerializer<?>> serializers;
+ /**
+ * Serializer for {@code text/plain} which is a serializer exclusive to HTTP.
+ */
+ private static final TextPlainMessageSerializer textPlainSerializer = new TextPlainMessageSerializer();
+
private final GremlinExecutor gremlinExecutor;
private final GraphManager graphManager;
private final Settings settings;
@@ -244,7 +253,7 @@
attemptCommit(requestArguments.getValue3(), graphManager, settings.strictTransactionManagement);
try {
- return Unpooled.wrappedBuffer(serializer.getValue1().serializeResponseAsString(responseMessage).getBytes(UTF8));
+ return Unpooled.wrappedBuffer(serializer.getValue1().serializeResponseAsString(responseMessage, ctx.alloc()).getBytes(UTF8));
} catch (Exception ex) {
logger.warn(String.format("Error during serialization for %s", responseMessage), ex);
@@ -352,6 +361,9 @@
final String accept = p.getValue0().equals("*/*") ? "application/json" : p.getValue0();
if (serializers.containsKey(accept))
return Pair.with(accept, (MessageTextSerializer<?>) serializers.get(accept));
+ else if (accept.equals("text/plain")) {
+ return Pair.with(accept, textPlainSerializer);
+ }
}
return null;
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractOpProcessor.java
index e3d38b9..49b9f6f 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractOpProcessor.java
@@ -299,7 +299,7 @@
.code(code)
.statusAttributes(statusAttributes)
.responseMetaData(responseMetaData)
- .result(aggregate).create()));
+ .result(aggregate).create(), nettyContext.alloc()));
}
} catch (Exception ex) {
logger.warn("The result [{}] in the request {} could not be serialized and returned.", aggregate, msg.getRequestId(), ex);
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializer.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializer.java
new file mode 100644
index 0000000..fe6cdbf
--- /dev/null
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializer.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.server.util;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.ser.MessageTextSerializer;
+import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Function;
+
+/**
+ * A highly use-case specific serializer that only has context for HTTP where results simply need to be converted
+ * to string in a line by line fashion for text based returns.
+ */
+public class TextPlainMessageSerializer implements MessageTextSerializer<Function<Object, String>> {
+
+ @Override
+ public Function<Object, String> getMapper() {
+ return Objects::toString;
+ }
+
+ @Override
+ public ByteBuf serializeResponseAsBinary(final ResponseMessage responseMessage, final ByteBufAllocator allocator) throws SerializationException {
+ throw new UnsupportedOperationException("text/plain does not produce binary");
+ }
+
+ @Override
+ public ByteBuf serializeRequestAsBinary(final RequestMessage requestMessage, final ByteBufAllocator allocator) throws SerializationException {
+ throw new UnsupportedOperationException("text/plain does not produce binary");
+ }
+
+ @Override
+ public RequestMessage deserializeRequest(final ByteBuf msg) throws SerializationException {
+ throw new UnsupportedOperationException("text/plain does not have deserialization functions");
+ }
+
+ @Override
+ public ResponseMessage deserializeResponse(final ByteBuf msg) throws SerializationException {
+ throw new UnsupportedOperationException("text/plain does not have deserialization functions");
+ }
+
+ @Override
+ public String[] mimeTypesSupported() {
+ return new String[] { "text/plain" };
+ }
+
+ @Override
+ public String serializeResponseAsString(final ResponseMessage responseMessage, final ByteBufAllocator allocator) throws SerializationException {
+ final StringBuilder sb = new StringBuilder();
+
+ // this should only serialize success conditions so all should have data in List form
+ final List<Object> data = (List<Object>) responseMessage.getResult().getData();
+ for (int ix = 0; ix < data.size(); ix ++) {
+ sb.append("==>");
+ sb.append(data.get(ix));
+ if (ix < data.size() - 1)
+ sb.append(System.lineSeparator());
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public String serializeRequestAsString(final RequestMessage requestMessage, final ByteBufAllocator allocator) throws SerializationException {
+ throw new UnsupportedOperationException("text/plain does not have any need to serialize requests");
+ }
+
+ @Override
+ public RequestMessage deserializeRequest(final String msg) throws SerializationException {
+ throw new UnsupportedOperationException("text/plain does not have deserialization functions");
+ }
+
+ @Override
+ public ResponseMessage deserializeResponse(final String msg) throws SerializationException {
+ throw new UnsupportedOperationException("text/plain does not have deserialization functions");
+ }
+}
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 028583f..b52bda0 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java
@@ -20,6 +20,8 @@
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.http.HttpHeaders;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV1d0;
import org.apache.tinkerpop.gremlin.util.Tokens;
import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV2d0;
@@ -36,15 +38,17 @@
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.tinkerpop.gremlin.server.handler.SaslAndHttpBasicAuthenticationHandler;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry;
import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONTokens;
import org.apache.tinkerpop.shaded.jackson.databind.JsonNode;
import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
import org.junit.Test;
-import java.io.File;
import java.time.Instant;
import java.util.Base64;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
@@ -54,7 +58,9 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.hamcrest.core.StringContains.containsString;
+import static org.hamcrest.core.StringRegularExpression.matchesRegex;
import static org.hamcrest.core.StringStartsWith.startsWith;
import static org.junit.Assert.assertEquals;
@@ -366,6 +372,68 @@
}
@Test
+ public void should200OnGETWithGremlinQueryStringArgumentWithIteratorResultGraphBinary() throws Exception {
+ final CloseableHttpClient httpclient = HttpClients.createDefault();
+ final HttpGet httpget = new HttpGet(TestClientFactory.createURLString("?gremlin=gclassic.V()"));
+ final String mime = SerTokens.MIME_GRAPHBINARY_V1D0;
+ httpget.addHeader("Accept", mime);
+
+ try (final CloseableHttpResponse response = httpclient.execute(httpget)) {
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ assertEquals(mime, response.getEntity().getContentType().getValue());
+ final String base64 = EntityUtils.toString(response.getEntity());
+ final GraphBinaryMessageSerializerV1 serializer = new GraphBinaryMessageSerializerV1(TypeSerializerRegistry.INSTANCE);
+ final ResponseMessage msg = serializer.deserializeResponse(base64);
+ final List<Object> data = (List<Object>) msg.getResult().getData();
+ assertEquals(6, data.size());
+ for (Object o : data) {
+ assertThat(o, instanceOf(Vertex.class));
+ }
+ }
+ }
+
+ @Test
+ public void should200OnGETWithGremlinQueryStringArgumentWithIteratorResultGraphBinaryToString() throws Exception {
+ final CloseableHttpClient httpclient = HttpClients.createDefault();
+ final HttpGet httpget = new HttpGet(TestClientFactory.createURLString("?gremlin=gclassic.V()"));
+ final String mime = SerTokens.MIME_GRAPHBINARY_V1D0 + "-stringd";
+ httpget.addHeader("Accept", mime);
+
+ try (final CloseableHttpResponse response = httpclient.execute(httpget)) {
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ assertEquals(mime, response.getEntity().getContentType().getValue());
+ final String base64 = EntityUtils.toString(response.getEntity());
+ final GraphBinaryMessageSerializerV1 serializer = new GraphBinaryMessageSerializerV1(TypeSerializerRegistry.INSTANCE);
+ final ResponseMessage msg = serializer.deserializeResponse(base64);
+ final List<Object> data = (List<Object>) msg.getResult().getData();
+ assertEquals(6, data.size());
+ for (Object o : data) {
+ assertThat(o, instanceOf(String.class));
+ assertThat((String) o, matchesRegex("v\\[\\d\\]"));
+ }
+ }
+ }
+
+ @Test
+ public void should200OnGETWithGremlinQueryStringArgumentWithIteratorResultTextPlain() throws Exception {
+ final CloseableHttpClient httpclient = HttpClients.createDefault();
+ final HttpGet httpget = new HttpGet(TestClientFactory.createURLString("?gremlin=gclassic.V()"));
+ final String mime = "text/plain";
+ httpget.addHeader("Accept", mime);
+
+ try (final CloseableHttpResponse response = httpclient.execute(httpget)) {
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ assertEquals(mime, response.getEntity().getContentType().getValue());
+ final String text = EntityUtils.toString(response.getEntity());
+ final String[] split = text.split(System.lineSeparator());
+ assertEquals(6, split.length);
+ for (String line : split) {
+ assertThat(line, matchesRegex("==>v\\[\\d\\]"));
+ }
+ }
+ }
+
+ @Test
public void should200OnGETWithGremlinQueryStringArgument() throws Exception {
final CloseableHttpClient httpclient = HttpClients.createDefault();
final HttpGet httpget = new HttpGet(TestClientFactory.createURLString("?gremlin=2-1"));
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializerTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializerTest.java
new file mode 100644
index 0000000..b88daaf
--- /dev/null
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializerTest.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.server.util;
+
+import io.netty.buffer.ByteBufAllocator;
+import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import static org.junit.Assert.assertEquals;
+
+public class TextPlainMessageSerializerTest {
+
+ @Test
+ public void shouldProducePlainText() throws Exception {
+ final Map<String, Object> m = new HashMap<>();
+ final ResponseMessage msg = ResponseMessage.build(UUID.randomUUID()).
+ result(Arrays.asList(1, new DetachedVertex(100, "person", m), java.awt.Color.RED)).create();
+
+ final TextPlainMessageSerializer messageSerializer = new TextPlainMessageSerializer();
+ final String output = messageSerializer.serializeResponseAsString(msg, ByteBufAllocator.DEFAULT);
+ final String exp = "==>1" + System.lineSeparator() +
+ "==>v[100]" + System.lineSeparator() +
+ "==>java.awt.Color[r=255,g=0,b=0]";
+ assertEquals(exp, output);
+ }
+}
diff --git a/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/TestWSGremlinInitializer.java b/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/TestWSGremlinInitializer.java
index 489d835..f8f48e2 100644
--- a/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/TestWSGremlinInitializer.java
+++ b/gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/TestWSGremlinInitializer.java
@@ -19,6 +19,7 @@
package org.apache.tinkerpop.gremlin.socket.server;
import io.netty.buffer.ByteBufAllocator;
+import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import org.apache.tinkerpop.gremlin.util.ser.AbstractMessageSerializer;
@@ -63,6 +64,7 @@
* Gremlin serializer used for serializing/deserializing the request/response. This should be same as client.
*/
private static AbstractMessageSerializer SERIALIZER;
+ private final static ByteBufAllocator allocator = UnpooledByteBufAllocator.DEFAULT;
public TestWSGremlinInitializer(final SocketServerSettings settings) {
this.settings = settings;
@@ -131,7 +133,7 @@
final ResponseMessage responseMessage = ResponseMessage.build(msg)
.code(ResponseStatusCode.SERVER_ERROR)
.statusAttributeException(new RuntimeException()).create();
- ctx.channel().writeAndFlush(new BinaryWebSocketFrame(SERIALIZER.serializeResponseAsBinary(responseMessage, ByteBufAllocator.DEFAULT)));
+ ctx.channel().writeAndFlush(new BinaryWebSocketFrame(SERIALIZER.serializeResponseAsBinary(responseMessage, allocator)));
} else if (msg.getRequestId().equals(settings.CLOSE_CONNECTION_REQUEST_ID) || msg.getRequestId().equals(settings.CLOSE_CONNECTION_REQUEST_ID_2)) {
Thread.sleep(1000);
ctx.channel().writeAndFlush(new CloseWebSocketFrame());
@@ -159,7 +161,7 @@
final List<Vertex> t = new ArrayList<>(1);
t.add(g.V().limit(1).next());
- return SERIALIZER.serializeResponseAsBinary(ResponseMessage.build(requestID).result(t).create(), ByteBufAllocator.DEFAULT);
+ return SERIALIZER.serializeResponseAsBinary(ResponseMessage.build(requestID).result(t).create(), allocator);
}
/**
@@ -170,7 +172,7 @@
//Need to package message in a list of size 1 as some GLV's serializers require all messages to be in a list
final List<String> messageList = new ArrayList<>(1);
messageList.add(message);
- return SERIALIZER.serializeResponseAsBinary(ResponseMessage.build(requestID).result(messageList).create(), ByteBufAllocator.DEFAULT);
+ return SERIALIZER.serializeResponseAsBinary(ResponseMessage.build(requestID).result(messageList).create(), allocator);
}
/**
diff --git a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphBinaryMessageSerializerV1.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphBinaryMessageSerializerV1.java
index 876dd45..28adcf3 100644
--- a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphBinaryMessageSerializerV1.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphBinaryMessageSerializerV1.java
@@ -20,6 +20,7 @@
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
+import io.netty.buffer.Unpooled;
import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryIo;
@@ -36,6 +37,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
+import java.util.Base64;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -43,7 +45,7 @@
import static java.nio.charset.StandardCharsets.UTF_8;
-public class GraphBinaryMessageSerializerV1 extends AbstractMessageSerializer<GraphBinaryMapper> {
+public class GraphBinaryMessageSerializerV1 extends AbstractMessageSerializer<GraphBinaryMapper> implements MessageTextSerializer<GraphBinaryMapper> {
public static final String TOKEN_CUSTOM = "custom";
public static final String TOKEN_BUILDER = "builder";
@@ -52,6 +54,9 @@
private static final String MIME_TYPE = SerTokens.MIME_GRAPHBINARY_V1D0;
private static final String MIME_TYPE_STRINGD = SerTokens.MIME_GRAPHBINARY_V1D0 + "-stringd";
+ private static final Base64.Encoder base64Encoder = Base64.getEncoder();
+ private static final Base64.Decoder base64Decoder = Base64.getDecoder();
+
private byte[] header = MIME_TYPE.getBytes(UTF_8);
private boolean serializeToString = false;
private GraphBinaryReader reader;
@@ -185,6 +190,41 @@
return new String[]{serializeToString ? MIME_TYPE_STRINGD : MIME_TYPE};
}
+ @Override
+ public String serializeResponseAsString(final ResponseMessage responseMessage, final ByteBufAllocator allocator) throws SerializationException {
+ final ByteBuf bb = serializeResponseAsBinary(responseMessage, allocator);
+ return base64Encoder.encodeToString(convertToBytes(bb));
+ }
+
+ @Override
+ public String serializeRequestAsString(final RequestMessage requestMessage, final ByteBufAllocator allocator) throws SerializationException {
+ final ByteBuf bb = serializeRequestAsBinary(requestMessage, allocator);
+ return base64Encoder.encodeToString(convertToBytes(bb));
+ }
+
+ @Override
+ public RequestMessage deserializeRequest(final String msg) throws SerializationException {
+ return deserializeRequest(convertToByteBuf(msg));
+ }
+
+ @Override
+ public ResponseMessage deserializeResponse(final String msg) throws SerializationException {
+ return deserializeResponse(convertToByteBuf(msg));
+ }
+
+ private byte[] convertToBytes(final ByteBuf bb) {
+ byte[] bytes = new byte[bb.readableBytes()];
+ bb.getBytes(bb.readerIndex(), bytes);
+ return bytes;
+ }
+
+ private ByteBuf convertToByteBuf(final String msg) {
+ final byte[] b = base64Decoder.decode(msg);
+ final ByteBuf bb = Unpooled.buffer(b.length);
+ bb.writeBytes(b);
+ return bb;
+ }
+
private void addCustomClasses(final Map<String, Object> config, final TypeSerializerRegistry.Builder builder) {
final List<String> classNameList = getListStringFromConfig(TOKEN_CUSTOM, config);
diff --git a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV1d0.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV1d0.java
index ff08eef..c1291bf 100644
--- a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV1d0.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV1d0.java
@@ -18,6 +18,7 @@
*/
package org.apache.tinkerpop.gremlin.util.ser;
+import io.netty.buffer.ByteBufAllocator;
import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
@@ -95,7 +96,7 @@
}
@Override
- public String serializeResponseAsString(final ResponseMessage responseMessage) throws SerializationException {
+ public String serializeResponseAsString(final ResponseMessage responseMessage, final ByteBufAllocator allocator) throws SerializationException {
try {
return mapper.writeValueAsString(responseMessage);
} catch (Exception ex) {
@@ -115,7 +116,7 @@
}
@Override
- public String serializeRequestAsString(final RequestMessage requestMessage) throws SerializationException {
+ public String serializeRequestAsString(final RequestMessage requestMessage, final ByteBufAllocator allocator) throws SerializationException {
try {
return mapper.writeValueAsString(requestMessage);
} catch (Exception ex) {
diff --git a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV2d0.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV2d0.java
index 89efc47..d0a434a 100644
--- a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV2d0.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV2d0.java
@@ -18,6 +18,7 @@
*/
package org.apache.tinkerpop.gremlin.util.ser;
+import io.netty.buffer.ByteBufAllocator;
import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
@@ -108,7 +109,7 @@
}
@Override
- public String serializeResponseAsString(final ResponseMessage responseMessage) throws SerializationException {
+ public String serializeResponseAsString(final ResponseMessage responseMessage, final ByteBufAllocator allocator) throws SerializationException {
try {
return mapper.writeValueAsString(responseMessage);
} catch (Exception ex) {
@@ -128,7 +129,7 @@
}
@Override
- public String serializeRequestAsString(final RequestMessage requestMessage) throws SerializationException {
+ public String serializeRequestAsString(final RequestMessage requestMessage, final ByteBufAllocator allocator) throws SerializationException {
try {
return mapper.writeValueAsString(requestMessage);
} catch (Exception ex) {
diff --git a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV3d0.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV3d0.java
index acdbffd..8021392 100644
--- a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV3d0.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV3d0.java
@@ -18,6 +18,7 @@
*/
package org.apache.tinkerpop.gremlin.util.ser;
+import io.netty.buffer.ByteBufAllocator;
import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
@@ -106,7 +107,7 @@
}
@Override
- public String serializeResponseAsString(final ResponseMessage responseMessage) throws SerializationException {
+ public String serializeResponseAsString(final ResponseMessage responseMessage, final ByteBufAllocator allocator) throws SerializationException {
try {
return mapper.writeValueAsString(responseMessage);
} catch (Exception ex) {
@@ -126,7 +127,7 @@
}
@Override
- public String serializeRequestAsString(final RequestMessage requestMessage) throws SerializationException {
+ public String serializeRequestAsString(final RequestMessage requestMessage, final ByteBufAllocator allocator) throws SerializationException {
try {
return mapper.writeValueAsString(requestMessage);
} catch (Exception ex) {
diff --git a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/MessageTextSerializer.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/MessageTextSerializer.java
index d81af2b..7d46aab 100644
--- a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/MessageTextSerializer.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/MessageTextSerializer.java
@@ -18,6 +18,7 @@
*/
package org.apache.tinkerpop.gremlin.util.ser;
+import io.netty.buffer.ByteBufAllocator;
import org.apache.tinkerpop.gremlin.util.MessageSerializer;
import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
@@ -31,9 +32,9 @@
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
public interface MessageTextSerializer<M> extends MessageSerializer<M> {
- public String serializeResponseAsString(final ResponseMessage responseMessage) throws SerializationException;
+ public String serializeResponseAsString(final ResponseMessage responseMessage, final ByteBufAllocator allocator) throws SerializationException;
- public String serializeRequestAsString(final RequestMessage requestMessage) throws SerializationException;
+ public String serializeRequestAsString(final RequestMessage requestMessage, final ByteBufAllocator allocator) throws SerializationException;
public RequestMessage deserializeRequest(final String msg) throws SerializationException;
diff --git a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV1d0Test.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV1d0Test.java
index 8e45448..d5d3d24 100644
--- a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV1d0Test.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV1d0Test.java
@@ -18,6 +18,7 @@
*/
package org.apache.tinkerpop.gremlin.util.ser;
+import io.netty.buffer.ByteBufAllocator;
import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
@@ -74,6 +75,7 @@
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 static final ByteBufAllocator allocator = ByteBufAllocator.DEFAULT;
@Test
public void shouldConfigureIoRegistry() throws Exception {
@@ -86,7 +88,7 @@
final ResponseMessage toSerialize = ResponseMessage.build(UUID.fromString("2D62161B-9544-4F39-AF44-62EC49F9A595"))
.result(Color.RED).create();
- final String results = serializer.serializeResponseAsString(toSerialize);
+ 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));
@@ -95,7 +97,7 @@
@Test
public void shouldSerializeToJsonNullResultReturnsNull() throws Exception {
final ResponseMessage message = ResponseMessage.build(msg).create();
- final String results = SERIALIZER.serializeResponseAsString(message);
+ final String results = SERIALIZER.serializeResponseAsString(message, allocator);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
assertEquals(msg.getRequestId().toString(), json.path(SerTokens.TOKEN_REQUEST).asText());
@@ -108,7 +110,7 @@
funList.add(new FunObject("x"));
funList.add(new FunObject("y"));
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(funList).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(funList).create(), allocator);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
@@ -127,7 +129,7 @@
funList.add(new FunObject("x"));
funList.add(new FunObject("y"));
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(funList.iterator()).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(funList.iterator()).create(), allocator);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
@@ -148,7 +150,7 @@
funList.add(null);
funList.add(new FunObject("y"));
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(funList.iterator()).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(funList.iterator()).create(), allocator);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
@@ -172,7 +174,7 @@
map.put("y", "some");
map.put("z", innerMap);
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(map).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(map).create(), allocator);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
@@ -199,7 +201,7 @@
map.put(v1, 100);
map.put(d, "test");
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(IteratorUtils.asList(map)).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(IteratorUtils.asList(map)).create(), allocator);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
@@ -226,7 +228,7 @@
e.property("abc", 123);
final Iterable<Edge> iterable = IteratorUtils.list(g.edges());
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(iterable).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(iterable).create(), allocator);
final JsonNode json = mapper.readTree(results);
@@ -260,7 +262,7 @@
e.property("abc", 123);
final Iterable<Property<Object>> iterable = IteratorUtils.list(e.properties("abc"));
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(iterable).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(iterable).create(), allocator);
final JsonNode json = mapper.readTree(results);
@@ -293,7 +295,7 @@
v.property(VertexProperty.Cardinality.single, "friends", friends);
final Iterable iterable = IteratorUtils.list(g.vertices());
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(iterable).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(iterable).create(), allocator);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
@@ -334,7 +336,7 @@
final Map<Vertex, Integer> map = new HashMap<>();
map.put(g.V().has("name", "marko").next(), 1000);
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(map).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(map).create(), allocator);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
@@ -393,7 +395,7 @@
.statusMessage("worked")
.create();
- final String results = SERIALIZER.serializeResponseAsString(response);
+ final String results = SERIALIZER.serializeResponseAsString(response, allocator);
final ResponseMessage deserialized = SERIALIZER.deserializeResponse(results);
assertEquals(id, deserialized.getRequestId());
@@ -423,7 +425,7 @@
.statusMessage(null)
.create();
- final String results = SERIALIZER.serializeResponseAsString(response);
+ 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);
@@ -436,7 +438,7 @@
final Tree t = g.V(1).out().properties("name").tree().next();
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(t).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(t).create(), allocator);
final JsonNode json = mapper.readTree(results);
diff --git a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV2d0Test.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV2d0Test.java
index a091006..2a0bf47 100644
--- a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV2d0Test.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV2d0Test.java
@@ -104,7 +104,7 @@
final ResponseMessage toSerialize = ResponseMessage.build(UUID.fromString("2D62161B-9544-4F39-AF44-62EC49F9A595"))
.result(Color.RED).create();
- final String results = serializer.serializeResponseAsString(toSerialize);
+ 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));
@@ -113,7 +113,7 @@
@Test
public void shouldSerializeToJsonNullResultReturnsNull() throws Exception {
final ResponseMessage message = ResponseMessage.build(msg).create();
- final String results = SERIALIZER.serializeResponseAsString(message);
+ final String results = SERIALIZER.serializeResponseAsString(message, allocator);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
assertEquals(msg.getRequestId().toString(), json.path(SerTokens.TOKEN_REQUEST).asText());
@@ -126,7 +126,7 @@
funList.add(new FunObject("x"));
funList.add(new FunObject("y"));
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(funList).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(funList).create(), allocator);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
@@ -145,7 +145,7 @@
funList.add(new FunObject("x"));
funList.add(new FunObject("y"));
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(funList).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(funList).create(), allocator);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
@@ -166,7 +166,7 @@
funList.add(null);
funList.add(new FunObject("y"));
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(funList.iterator()).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(funList.iterator()).create(), allocator);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
@@ -190,7 +190,7 @@
map.put("y", "some");
map.put("z", innerMap);
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(map).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(map).create(), allocator);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
@@ -217,7 +217,7 @@
map.put(v1, 100);
map.put(d, "test");
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(IteratorUtils.asList(map)).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(IteratorUtils.asList(map)).create(), allocator);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
@@ -244,7 +244,7 @@
e.property("abc", 123);
final Iterable<Edge> iterable = IteratorUtils.list(g.edges());
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(iterable).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(iterable).create(), allocator);
final JsonNode json = mapper.readTree(results);
@@ -277,7 +277,7 @@
e.property("abc", 123);
final Iterable<Property<Object>> iterable = IteratorUtils.list(e.properties("abc"));
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(iterable).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(iterable).create(), allocator);
final JsonNode json = mapper.readTree(results);
@@ -310,7 +310,7 @@
v.property(VertexProperty.Cardinality.single, "friends", friends);
final Iterable iterable = IteratorUtils.list(g.vertices());
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(iterable).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(iterable).create(), allocator);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
@@ -351,7 +351,7 @@
final Map<Vertex, Integer> map = new HashMap<>();
map.put(g.V().has("name", "marko").next(), 1000);
- final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(map).create());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(map).create(), allocator);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
@@ -410,7 +410,7 @@
.statusMessage("worked")
.create();
- final String results = SERIALIZER.serializeResponseAsString(response);
+ final String results = SERIALIZER.serializeResponseAsString(response, allocator);
final ResponseMessage deserialized = SERIALIZER.deserializeResponse(results);
assertEquals(id, deserialized.getRequestId());
@@ -429,7 +429,7 @@
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());
+ final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(t).create(), allocator);
final JsonNode json = mapper.readTree(results);
diff --git a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryMessageSerializerV1Test.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryMessageSerializerV1Test.java
index 8813491..c4b486f 100644
--- a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryMessageSerializerV1Test.java
+++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryMessageSerializerV1Test.java
@@ -175,6 +175,43 @@
assertEquals(java.awt.Color.RED.toString(), deserialized.getResult().getData());
}
+ @Test
+ public void shouldToStringSerializeAsText() throws SerializationException {
+ final GraphBinaryMessageSerializerV1 serializer = new GraphBinaryMessageSerializerV1();
+ final Map<String,Object> conf = new HashMap<String,Object>() {{
+ put(GraphBinaryMessageSerializerV1.TOKEN_SERIALIZE_RESULT_TO_STRING, true);
+ }};
+ serializer.configure(conf, Collections.emptyMap());
+
+ final ResponseMessage messageWithUnexpectedType = ResponseMessage.build(UUID.randomUUID()).
+ result(java.awt.Color.RED).create();
+ final String base64 = serializer.serializeResponseAsString(messageWithUnexpectedType, allocator);
+ final ResponseMessage deserialized = serializer.deserializeResponse(base64);
+
+ assertEquals(java.awt.Color.RED.toString(), deserialized.getResult().getData());
+ }
+
+ @Test
+ public void shouldSerializeAndDeserializeRequestAsText() throws SerializationException {
+ final GraphBinaryMessageSerializerV1 serializer = new GraphBinaryMessageSerializerV1();
+ final Map<String,Object> conf = new HashMap<String,Object>() {{
+ put(GraphBinaryMessageSerializerV1.TOKEN_SERIALIZE_RESULT_TO_STRING, true);
+ }};
+ serializer.configure(conf, Collections.emptyMap());
+
+ final RequestMessage request = RequestMessage.build("op1")
+ .processor("proc1")
+ .overrideRequestId(UUID.randomUUID())
+ .addArg("arg1", "value1")
+ .create();
+
+ final ByteBuf buffer = serializer.serializeRequestAsBinary(request, allocator);
+ final int mimeLen = buffer.readByte();
+ buffer.readBytes(new byte[mimeLen]);
+ final RequestMessage deserialized = serializer.deserializeRequest(buffer);
+ assertThat(request, reflectionEquals(deserialized));
+ }
+
private static void assertResponseEquals(ResponseMessage expected, ResponseMessage actual) {
assertEquals(expected.getRequestId(), actual.getRequestId());
// Status