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/05/25 12:26:18 UTC

[tinkerpop] branch master updated (c7d0a597a8 -> a83bb3db20)

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

spmallette pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git


    from c7d0a597a8 Fixed up doc generation for spark/hadoop. CTR
     add eab6f698c7 Hardcode the spark-yarn example.
     add 3afa71742a Merge branch '3.5-dev' into 3.6-dev
     add d0c1346b30 TINKERPOP-2947 Added text/plain and text serialization for graphbinary for HTTP endpoint
     add ac00aff3b7 Merge branch 'TINKERPOP-2947' into 3.6-dev
     new a83bb3db20 Merge branch '3.6-dev'

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 CHANGELOG.asciidoc                                 |  4 +-
 docs/src/recipes/olap-spark-yarn.asciidoc          | 58 ++++++++-----
 docs/src/reference/gremlin-applications.asciidoc   | 15 ++++
 docs/src/upgrade/release-3.6.x.asciidoc            | 17 ++++
 .../handler/WebSocketGremlinRequestEncoder.java    |  2 +-
 .../gremlin/server/handler/AbstractSession.java    |  2 +-
 .../handler/GremlinResponseFrameEncoder.java       |  6 +-
 .../server/handler/HttpGremlinEndpointHandler.java | 14 +++-
 .../gremlin/server/op/AbstractOpProcessor.java     |  2 +-
 .../server/util/TextPlainMessageSerializer.java    | 97 ++++++++++++++++++++++
 .../server/GremlinServerHttpIntegrateTest.java     | 70 +++++++++++++++-
 .../util/TextPlainMessageSerializerTest.java       | 48 +++++++++++
 .../socket/server/TestWSGremlinInitializer.java    |  8 +-
 .../util/ser/GraphBinaryMessageSerializerV1.java   | 42 +++++++++-
 .../util/ser/GraphSONMessageSerializerV1d0.java    |  5 +-
 .../util/ser/GraphSONMessageSerializerV2d0.java    |  5 +-
 .../util/ser/GraphSONMessageSerializerV3d0.java    |  5 +-
 .../gremlin/util/ser/MessageTextSerializer.java    |  5 +-
 .../ser/GraphSONMessageSerializerV1d0Test.java     | 30 +++----
 .../ser/GraphSONMessageSerializerV2d0Test.java     | 26 +++---
 .../binary/GraphBinaryMessageSerializerV1Test.java | 37 +++++++++
 21 files changed, 431 insertions(+), 67 deletions(-)
 create mode 100644 gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializer.java
 create mode 100644 gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializerTest.java


[tinkerpop] 01/01: Merge branch '3.6-dev'

Posted by sp...@apache.org.
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 a83bb3db200231bea24d71c0a34deb98b2176dd0
Merge: c7d0a597a8 ac00aff3b7
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Thu May 25 08:26:03 2023 -0400

    Merge branch '3.6-dev'

 CHANGELOG.asciidoc                                 |  4 +-
 docs/src/recipes/olap-spark-yarn.asciidoc          | 58 ++++++++-----
 docs/src/reference/gremlin-applications.asciidoc   | 15 ++++
 docs/src/upgrade/release-3.6.x.asciidoc            | 17 ++++
 .../handler/WebSocketGremlinRequestEncoder.java    |  2 +-
 .../gremlin/server/handler/AbstractSession.java    |  2 +-
 .../handler/GremlinResponseFrameEncoder.java       |  6 +-
 .../server/handler/HttpGremlinEndpointHandler.java | 14 +++-
 .../gremlin/server/op/AbstractOpProcessor.java     |  2 +-
 .../server/util/TextPlainMessageSerializer.java    | 97 ++++++++++++++++++++++
 .../server/GremlinServerHttpIntegrateTest.java     | 70 +++++++++++++++-
 .../util/TextPlainMessageSerializerTest.java       | 48 +++++++++++
 .../socket/server/TestWSGremlinInitializer.java    |  8 +-
 .../util/ser/GraphBinaryMessageSerializerV1.java   | 42 +++++++++-
 .../util/ser/GraphSONMessageSerializerV1d0.java    |  5 +-
 .../util/ser/GraphSONMessageSerializerV2d0.java    |  5 +-
 .../util/ser/GraphSONMessageSerializerV3d0.java    |  5 +-
 .../gremlin/util/ser/MessageTextSerializer.java    |  5 +-
 .../ser/GraphSONMessageSerializerV1d0Test.java     | 30 +++----
 .../ser/GraphSONMessageSerializerV2d0Test.java     | 26 +++---
 .../binary/GraphBinaryMessageSerializerV1Test.java | 37 +++++++++
 21 files changed, 431 insertions(+), 67 deletions(-)

diff --cc gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
index 6e0217b5b7,6995b21583..7eda64514c
--- 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,10 +19,14 @@@
  package org.apache.tinkerpop.gremlin.server.handler;
  
  import com.codahale.metrics.Timer;
 -import io.netty.buffer.ByteBufAllocator;
 -import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
 -import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
++import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 +import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptChecker;
 +import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.AbstractTraverser;
 +import org.apache.tinkerpop.gremlin.structure.Element;
 +import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceFactory;
 +import org.apache.tinkerpop.gremlin.util.Tokens;
 +import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
+ import org.apache.tinkerpop.gremlin.server.util.TextPlainMessageSerializer;
  import org.javatuples.Pair;
  import org.javatuples.Quartet;
  import org.slf4j.Logger;
diff --cc gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializer.java
index 0000000000,81b3662b96..fe6cdbf7d9
mode 000000,100644..100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializer.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializer.java
@@@ -1,0 -1,97 +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.driver.message.RequestMessage;
 -import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
 -import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
 -import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
++import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
++import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
++import org.apache.tinkerpop.gremlin.util.ser.MessageTextSerializer;
++import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
+ 
+ import java.util.List;
+ import java.util.Objects;
+ 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 --cc gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java
index 028583f90b,4f44158dd6..b52bda0ce9
--- 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,11 -20,13 +20,13 @@@ package org.apache.tinkerpop.gremlin.se
  
  import org.apache.commons.lang3.RandomStringUtils;
  import org.apache.http.HttpHeaders;
 -import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
 -import org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1;
 -import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0;
 -import org.apache.tinkerpop.gremlin.driver.Tokens;
 -import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV2d0;
 -import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0;
 -import org.apache.tinkerpop.gremlin.driver.ser.SerTokens;
++import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
++import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
 +import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV1d0;
 +import org.apache.tinkerpop.gremlin.util.Tokens;
 +import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV2d0;
 +import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0;
 +import org.apache.tinkerpop.gremlin.util.ser.SerTokens;
  import org.apache.tinkerpop.gremlin.server.auth.SimpleAuthenticator;
  import org.apache.tinkerpop.gremlin.server.channel.HttpChannelizer;
  import org.apache.http.Consts;
diff --cc gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializerTest.java
index 0000000000,803d1495fa..b88daaf589
mode 000000,100644..100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializerTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/util/TextPlainMessageSerializerTest.java
@@@ -1,0 -1,48 +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.driver.message.ResponseMessage;
++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 --cc gremlin-tools/gremlin-socket-server/src/main/java/org/apache/tinkerpop/gremlin/socket/server/TestWSGremlinInitializer.java
index 489d835a4f,0000000000..f8f48e2f3e
mode 100644,000000..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
@@@ -1,193 -1,0 +1,195 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + * http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.tinkerpop.gremlin.socket.server;
 +
 +import io.netty.buffer.ByteBufAllocator;
++import io.netty.buffer.UnpooledByteBufAllocator;
 +import io.netty.handler.codec.http.HttpHeaders;
 +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
 +import org.apache.tinkerpop.gremlin.util.ser.AbstractMessageSerializer;
 +import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
 +import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3d0;
 +import org.slf4j.Logger;
 +import org.slf4j.LoggerFactory;
 +import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 +import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
 +import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 +import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV2d0;
 +import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
 +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 +import org.apache.tinkerpop.gremlin.structure.Vertex;
 +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
 +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
 +import io.netty.buffer.ByteBuf;
 +import io.netty.channel.ChannelHandlerContext;
 +import io.netty.channel.ChannelPipeline;
 +import io.netty.handler.codec.MessageToMessageDecoder;
 +import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
 +import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
 +
 +import java.util.ArrayList;
 +import java.util.List;
 +import java.util.UUID;
 +
 +
 +/**
 + * Initializer which partially mimics the Gremlin Server. This initializer injects a handler in the
 + * server pipeline that can be modified to send the desired response for a test case.
 + * This handler identifies incoming requests with ids matching those in {@link SocketServerSettings}
 + * and delivers the response which corresponds to the request id.
 + */
 +public class TestWSGremlinInitializer extends TestChannelizers.TestWebSocketServerInitializer {
 +    private static final Logger logger = LoggerFactory.getLogger(TestWSGremlinInitializer.class);
 +    private static final String USER_AGENT_HEADER = "User-Agent";
 +
 +    private final SocketServerSettings settings;
 +
 +    /**
 +     * Gremlin serializer used for serializing/deserializing the request/response. This should be same as client.
 +     */
 +    private static AbstractMessageSerializer SERIALIZER;
++    private final static ByteBufAllocator allocator = UnpooledByteBufAllocator.DEFAULT;
 +
 +    public TestWSGremlinInitializer(final SocketServerSettings settings) {
 +        this.settings = settings;
 +        switch(settings.SERIALIZER) {
 +            case "GraphSONV2":
 +                SERIALIZER = new GraphSONMessageSerializerV2d0();
 +                break;
 +            case "GraphSONV3":
 +                SERIALIZER = new GraphSONMessageSerializerV3d0();
 +                break;
 +            case "GraphBinaryV1":
 +                SERIALIZER = new GraphBinaryMessageSerializerV1();
 +                break;
 +            default:
 +                logger.warn("Could not recognize serializer [%s], defaulting to GraphBinaryV1", settings.SERIALIZER);
 +                SERIALIZER = new GraphBinaryMessageSerializerV1();
 +                break;
 +        }
 +    }
 +
 +    @Override
 +    public void postInit(ChannelPipeline pipeline) {
 +        pipeline.addLast(new ClientTestConfigurableHandler(settings));
 +    }
 +
 +    /**
 +     * Handler introduced in the server pipeline to configure expected response for test cases.
 +     */
 +    static class ClientTestConfigurableHandler extends MessageToMessageDecoder<BinaryWebSocketFrame> {
 +        private SocketServerSettings settings;
 +        private String userAgent = "";
 +
 +        public ClientTestConfigurableHandler(SocketServerSettings settings) { this.settings = settings; }
 +
 +        @Override
 +        protected void decode(final ChannelHandlerContext ctx, final BinaryWebSocketFrame frame, final List<Object> objects)
 +                throws Exception {
 +            final ByteBuf messageBytes = frame.content();
 +            final byte len = messageBytes.readByte();
 +            if (len <= 0) {
 +                objects.add(RequestMessage.INVALID);
 +                return;
 +            }
 +
 +            final ByteBuf contentTypeBytes = ctx.alloc().buffer(len);
 +            try {
 +                messageBytes.readBytes(contentTypeBytes);
 +            } finally {
 +                contentTypeBytes.release();
 +            }
 +            final RequestMessage msg = SERIALIZER.deserializeRequest(messageBytes.discardReadBytes());
 +            if (msg.getRequestId().equals(settings.SINGLE_VERTEX_DELAYED_CLOSE_CONNECTION_REQUEST_ID)) {
 +                logger.info("sending vertex result frame");
 +                ctx.channel().writeAndFlush(new BinaryWebSocketFrame(returnSingleVertexResponse(
 +                        settings.SINGLE_VERTEX_DELAYED_CLOSE_CONNECTION_REQUEST_ID)));
 +                logger.info("waiting for 2 sec");
 +                Thread.sleep(2000);
 +                logger.info("sending close frame");
 +                ctx.channel().writeAndFlush(new CloseWebSocketFrame());
 +            } else if (msg.getRequestId().equals(settings.SINGLE_VERTEX_REQUEST_ID)) {
 +                logger.info("sending vertex result frame");
 +                ctx.channel().writeAndFlush(new BinaryWebSocketFrame(returnSingleVertexResponse(settings.SINGLE_VERTEX_REQUEST_ID)));
 +            } else if (msg.getRequestId().equals(settings.FAILED_AFTER_DELAY_REQUEST_ID)) {
 +                logger.info("waiting for 1 sec");
 +                Thread.sleep(1000);
 +                final ResponseMessage responseMessage = ResponseMessage.build(msg)
 +                        .code(ResponseStatusCode.SERVER_ERROR)
 +                        .statusAttributeException(new RuntimeException()).create();
-                 ctx.channel().writeAndFlush(new BinaryWebSocketFrame(SERIALIZER.serializeResponseAsBinary(responseMessage, 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());
 +            } else if (msg.getRequestId().equals(settings.USER_AGENT_REQUEST_ID)) {
 +                ctx.channel().writeAndFlush(new BinaryWebSocketFrame(returnSimpleBinaryResponse(settings.USER_AGENT_REQUEST_ID, userAgent)));
 +            } else if (msg.getRequestId().equals(settings.PER_REQUEST_SETTINGS_REQUEST_ID)) {
 +                String response = String.format("requestId=%s evaluationTimeout=%d, batchSize=%d, userAgent=%s",
 +                        msg.getRequestId(), msg.getArgs().get("evaluationTimeout"),
 +                        msg.getArgs().get("batchSize"), msg.getArgs().get("userAgent"));
 +                ctx.channel().writeAndFlush(new BinaryWebSocketFrame(returnSimpleBinaryResponse(settings.PER_REQUEST_SETTINGS_REQUEST_ID, response)));
 +            } else {
 +                try {
 +                    Thread.sleep(Long.parseLong((String) msg.getArgs().get("gremlin")));
 +                    ctx.channel().writeAndFlush(new BinaryWebSocketFrame(returnSingleVertexResponse(msg.getRequestId())));
 +                } catch (NumberFormatException nfe) {
 +                    // Ignore. Only return a vertex if the query was a long value.
 +                    logger.warn("Request unknown request with RequestId: %s", msg.getRequestId());
 +                }
 +            }
 +        }
 +
 +        private ByteBuf returnSingleVertexResponse(final UUID requestID) throws SerializationException {
 +            final TinkerGraph graph = TinkerFactory.createClassic();
 +            final GraphTraversalSource g = graph.traversal();
 +            final List<Vertex> t = new ArrayList<>(1);
 +            t.add(g.V().limit(1).next());
 +
-             return SERIALIZER.serializeResponseAsBinary(ResponseMessage.build(requestID).result(t).create(), ByteBufAllocator.DEFAULT);
++            return SERIALIZER.serializeResponseAsBinary(ResponseMessage.build(requestID).result(t).create(), allocator);
 +        }
 +
 +        /**
 +         * Packages a string message into a ResponseMessage and serializes it into a ByteBuf
 +         * @throws SerializationException
 +         */
 +        private ByteBuf returnSimpleBinaryResponse(final UUID requestID, String message) throws SerializationException {
 +            //Need to package message in a list of size 1 as some GLV's serializers require all messages to be in a list
 +            final List<String> messageList = new ArrayList<>(1);
 +            messageList.add(message);
-             return SERIALIZER.serializeResponseAsBinary(ResponseMessage.build(requestID).result(messageList).create(), ByteBufAllocator.DEFAULT);
++            return SERIALIZER.serializeResponseAsBinary(ResponseMessage.build(requestID).result(messageList).create(), allocator);
 +        }
 +
 +        /**
 +         * Captures and stores User-Agent if included in header
 +         */
 +        @Override
 +        public void userEventTriggered(final ChannelHandlerContext ctx, final Object evt) {
 +            if(evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
 +                WebSocketServerProtocolHandler.HandshakeComplete handshake = (WebSocketServerProtocolHandler.HandshakeComplete) evt;
 +                HttpHeaders requestHeaders = handshake.requestHeaders();
 +                if(requestHeaders.contains(USER_AGENT_HEADER)) {
 +                    userAgent = requestHeaders.get(USER_AGENT_HEADER);
 +                }
 +                else {
 +                    ctx.fireUserEventTriggered(evt);
 +                }
 +            }
 +        }
 +    }
 +}
diff --cc gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphBinaryMessageSerializerV1.java
index 876dd458b1,0000000000..28adcf3a8a
mode 100644,000000..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
@@@ -1,228 -1,0 +1,268 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + * http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.tinkerpop.gremlin.util.ser;
 +
 +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;
 +import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryMapper;
 +import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader;
 +import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter;
 +import org.apache.tinkerpop.gremlin.util.ser.binary.RequestMessageSerializer;
 +import org.apache.tinkerpop.gremlin.util.ser.binary.ResponseMessageSerializer;
 +import org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry;
 +import org.apache.tinkerpop.gremlin.structure.io.binary.types.CustomTypeSerializer;
 +import org.apache.tinkerpop.gremlin.structure.Graph;
 +import org.apache.tinkerpop.gremlin.structure.io.IoRegistry;
 +import org.javatuples.Pair;
 +
 +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;
 +import java.util.stream.Collectors;
 +
 +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";
 +    public static final String TOKEN_SERIALIZE_RESULT_TO_STRING = "serializeResultToString";
 +
 +    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;
 +    private GraphBinaryWriter writer;
 +    private RequestMessageSerializer requestSerializer;
 +    private ResponseMessageSerializer responseSerializer;
 +    private GraphBinaryMapper mapper;
 +
 +    /**
 +     * Creates a new instance of the message serializer using the default type serializers.
 +     */
 +    public GraphBinaryMessageSerializerV1() {
 +        this(TypeSerializerRegistry.INSTANCE);
 +    }
 +
 +    public GraphBinaryMessageSerializerV1(final TypeSerializerRegistry registry) {
 +        reader = new GraphBinaryReader(registry);
 +        writer = new GraphBinaryWriter(registry);
 +        mapper = new GraphBinaryMapper(writer, reader);
 +
 +        requestSerializer = new RequestMessageSerializer();
 +        responseSerializer = new ResponseMessageSerializer();
 +    }
 +
 +    public GraphBinaryMessageSerializerV1(final TypeSerializerRegistry.Builder builder) {
 +        this(builder.create());
 +    }
 +
 +    @Override
 +    public GraphBinaryMapper getMapper() {
 +        return mapper;
 +    }
 +
 +    @Override
 +    public void configure(final Map<String, Object> config, final Map<String, Graph> graphs) {
 +        final String builderClassName = (String) config.get(TOKEN_BUILDER);
 +        final TypeSerializerRegistry.Builder builder;
 +
 +        if (builderClassName != null) {
 +            try {
 +                final Class<?> clazz = Class.forName(builderClassName);
 +                final Constructor<?> ctor = clazz.getConstructor();
 +                builder = (TypeSerializerRegistry.Builder) ctor.newInstance();
 +            } catch (Exception ex) {
 +                throw new IllegalStateException(ex);
 +            }
 +        } else {
 +            builder = TypeSerializerRegistry.build();
 +        }
 +
 +        final List<String> classNameList = getListStringFromConfig(TOKEN_IO_REGISTRIES, config);
 +        classNameList.forEach(className -> {
 +            try {
 +                final Class<?> clazz = Class.forName(className);
 +                try {
 +                    final Method instanceMethod = tryInstanceMethod(clazz);
 +                    final IoRegistry ioreg = (IoRegistry) instanceMethod.invoke(null);
 +                    final List<Pair<Class, CustomTypeSerializer>> classSerializers = ioreg.find(GraphBinaryIo.class, CustomTypeSerializer.class);
 +                    for (Pair<Class,CustomTypeSerializer> cs : classSerializers) {
 +                        builder.addCustomType(cs.getValue0(), cs.getValue1());
 +                    }
 +                } catch (Exception methodex) {
 +                    throw new IllegalStateException(String.format("Could not instantiate IoRegistry from an instance() method on %s", className), methodex);
 +                }
 +            } catch (Exception ex) {
 +                throw new IllegalStateException(ex);
 +            }
 +        });
 +
 +        addCustomClasses(config, builder);
 +
 +        this.serializeToString = Boolean.parseBoolean(config.getOrDefault(TOKEN_SERIALIZE_RESULT_TO_STRING, "false").toString());
 +        this.header = this.serializeToString ? MIME_TYPE_STRINGD.getBytes(UTF_8) : MIME_TYPE.getBytes(UTF_8);
 +
 +        final TypeSerializerRegistry registry = builder.create();
 +        reader = new GraphBinaryReader(registry);
 +        writer = new GraphBinaryWriter(registry);
 +
 +        requestSerializer = new RequestMessageSerializer();
 +        responseSerializer = new ResponseMessageSerializer();
 +    }
 +
 +    @Override
 +    public ByteBuf serializeResponseAsBinary(final ResponseMessage responseMessage, final ByteBufAllocator allocator) throws SerializationException {
 +        final ByteBuf buffer = allocator.buffer();
 +
 +        try {
 +            final ResponseMessage msgToWrite = !serializeToString ? responseMessage :
 +                    ResponseMessage.build(responseMessage.getRequestId())
 +                            .code(responseMessage.getStatus().getCode())
 +                            .statusAttributes(responseMessage.getStatus().getAttributes())
 +                            .responseMetaData(responseMessage.getResult().getMeta())
 +                            .result(serializeResultToString(responseMessage))
 +                            .statusMessage(responseMessage.getStatus().getMessage()).create();
 +
 +            responseSerializer.writeValue(msgToWrite, buffer, writer);
 +        } catch (Exception ex) {
 +            buffer.release();
 +            throw ex;
 +        }
 +
 +        return buffer;
 +    }
 +
 +    @Override
 +    public ByteBuf serializeRequestAsBinary(final RequestMessage requestMessage, final ByteBufAllocator allocator) throws SerializationException {
 +        final ByteBuf buffer = allocator.buffer().writeByte(header.length).writeBytes(header);
 +
 +        try {
 +            requestSerializer.writeValue(requestMessage, buffer, writer);
 +        } catch (Exception ex) {
 +            buffer.release();
 +            throw ex;
 +        }
 +
 +        return buffer;
 +    }
 +
 +    @Override
 +    public RequestMessage deserializeRequest(final ByteBuf msg) throws SerializationException {
 +        return requestSerializer.readValue(msg, reader);
 +    }
 +
 +    @Override
 +    public ResponseMessage deserializeResponse(final ByteBuf msg) throws SerializationException {
 +        return responseSerializer.readValue(msg, reader);
 +    }
 +
 +    @Override
 +    public String[] mimeTypesSupported() {
 +        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);
 +
 +        classNameList.forEach(serializerDefinition -> {
 +            final String className;
 +            final String serializerName;
 +            if (serializerDefinition.contains(";")) {
 +                final String[] split = serializerDefinition.split(";");
 +                if (split.length != 2)
 +                    throw new IllegalStateException(String.format("Invalid format for serializer definition [%s] - expected <class>;<serializer-class>", serializerDefinition));
 +
 +                className = split[0];
 +                serializerName = split[1];
 +            } else {
 +                throw new IllegalStateException(String.format("Invalid format for serializer definition [%s] - expected <class>;<serializer-class>", serializerDefinition));
 +            }
 +
 +            try {
 +                final Class clazz = Class.forName(className);
 +                final Class serializerClazz = Class.forName(serializerName);
 +                final CustomTypeSerializer serializer = (CustomTypeSerializer) serializerClazz.newInstance();
 +                builder.addCustomType(clazz, serializer);
 +            } catch (Exception ex) {
 +                throw new IllegalStateException("CustomTypeSerializer could not be instantiated", ex);
 +            }
 +        });
 +    }
 +
 +    private Object serializeResultToString(final ResponseMessage msg) {
 +        if (msg.getResult() == null) return "null";
 +        if (msg.getResult().getData() == null) return "null";
 +
 +        // the IteratorHandler should return a collection so keep it as such
 +        final Object o = msg.getResult().getData();
 +        if (o instanceof Collection) {
 +            return ((Collection) o).stream().map(d -> null == d ? "null" : d.toString()).collect(Collectors.toList());
 +        } else {
 +            return o.toString();
 +        }
 +    }
 +}
diff --cc gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV1d0.java
index ff08eef4a0,0000000000..c1291bf498
mode 100644,000000..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
@@@ -1,126 -1,0 +1,127 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + * http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.tinkerpop.gremlin.util.ser;
 +
++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;
 +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;
 +import org.slf4j.LoggerFactory;
 +
 +import java.nio.ByteBuffer;
 +import java.util.Map;
 +import java.util.UUID;
 +
 +/**
 + * Serialize results to JSON with version 1.0.x schema.
 + *
 + * @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_JSON;
 +
 +    private static byte[] header;
 +
 +    static {
 +        final ByteBuffer buffer = ByteBuffer.allocate(MIME_TYPE.length() + 1);
 +        buffer.put((byte) MIME_TYPE.length());
 +        buffer.put(MIME_TYPE.getBytes());
 +        header = buffer.array();
 +    }
 +
 +    public GraphSONMessageSerializerV1d0() {
 +        super();
 +    }
 +
 +    public GraphSONMessageSerializerV1d0(final GraphSONMapper mapper) {
 +        super(mapper);
 +    }
 +
 +    @Override
 +    public String[] mimeTypesSupported() {
 +        return new String[]{MIME_TYPE};
 +    }
 +
 +    @Override
 +    GraphSONMapper.Builder configureBuilder(final GraphSONMapper.Builder builder) {
 +        // already set to 1.0 in AbstractGraphSONMessageSerializerV1d0
 +        return builder.addCustomModule(new GremlinServerModule())
 +                .typeInfo(TypeInfo.NO_TYPES);
 +    }
 +
 +    @Override
 +    byte[] obtainHeader() {
 +        return header;
 +    }
 +
 +    @Override
 +    public ResponseMessage deserializeResponse(final String msg) throws SerializationException {
 +        try {
 +            final Map<String, Object> responseData = mapper.readValue(msg, mapTypeReference);
 +            final Map<String, Object> status = (Map<String, Object>) responseData.get(SerTokens.TOKEN_STATUS);
 +            final Map<String, Object> result = (Map<String, Object>) responseData.get(SerTokens.TOKEN_RESULT);
 +            return ResponseMessage.build(UUID.fromString(responseData.get(SerTokens.TOKEN_REQUEST).toString()))
 +                    .code(ResponseStatusCode.getFromValue((Integer) status.get(SerTokens.TOKEN_CODE)))
 +                    .statusMessage(String.valueOf(status.get(SerTokens.TOKEN_MESSAGE)))
 +                    .statusAttributes((Map<String, Object>) status.get(SerTokens.TOKEN_ATTRIBUTES))
 +                    .result(result.get(SerTokens.TOKEN_DATA))
 +                    .responseMetaData((Map<String, Object>) result.get(SerTokens.TOKEN_META))
 +                    .create();
 +        } catch (Exception ex) {
 +            logger.warn("Response [{}] could not be deserialized by {}.", msg, AbstractGraphSONMessageSerializerV1d0.class.getName());
 +            throw new SerializationException(ex);
 +        }
 +    }
 +
 +    @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) {
 +            logger.warn("Response [{}] could not be serialized by {}.", responseMessage.toString(), AbstractGraphSONMessageSerializerV1d0.class.getName());
 +            throw new SerializationException(ex);
 +        }
 +    }
 +
 +    @Override
 +    public RequestMessage deserializeRequest(final String msg) throws SerializationException {
 +        try {
 +            return mapper.readValue(msg, RequestMessage.class);
 +        } catch (Exception ex) {
 +            logger.warn("Request [{}] could not be deserialized by {}.", msg, AbstractGraphSONMessageSerializerV1d0.class.getName());
 +            throw new SerializationException(ex);
 +        }
 +    }
 +
 +    @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) {
 +            logger.warn("Request [{}] could not be serialized by {}.", requestMessage.toString(), AbstractGraphSONMessageSerializerV1d0.class.getName());
 +            throw new SerializationException(ex);
 +        }
 +    }
 +}
diff --cc gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV2d0.java
index 89efc47414,0000000000..d0a434a90b
mode 100644,000000..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
@@@ -1,139 -1,0 +1,140 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + * http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.tinkerpop.gremlin.util.ser;
 +
++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;
 +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;
 +import org.slf4j.Logger;
 +import org.slf4j.LoggerFactory;
 +
 +import java.nio.ByteBuffer;
 +
 +/**
 + * Serialize results to JSON with version 2.0.x schema and the extended module.
 + *
 + * @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;
 +
 +    private static byte[] header;
 +
 +    static {
 +        final ByteBuffer buffer = ByteBuffer.allocate(MIME_TYPE.length() + 1);
 +        buffer.put((byte) MIME_TYPE.length());
 +        buffer.put(MIME_TYPE.getBytes());
 +        header = buffer.array();
 +    }
 +
 +        /**
 +         * 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)
 +         */
 +    public GraphSONMessageSerializerV2d0() {
 +        super();
 +    }
 +
 +    /**
 +     * Create a GraphSONMessageSerializer from a {@link GraphSONMapper}. Deprecated, use
 +     * {@link #GraphSONMessageSerializerV2d0(GraphSONMapper.Builder)} instead.
 +     */
 +    @Deprecated
 +    public GraphSONMessageSerializerV2d0(final GraphSONMapper mapper) {
 +        super(mapper);
 +    }
 +
 +    /**
 +     * Create a GraphSONMessageSerializer with a provided {@link GraphSONMapper.Builder}.
 +     *
 +     * Note that to make this mapper usable in the context of request messages and responses,
 +     * this method will automatically register a {@link GremlinServerModule} to the provided
 +     * mapper.
 +     */
 +    public GraphSONMessageSerializerV2d0(final GraphSONMapper.Builder mapperBuilder) {
 +        super(mapperBuilder);
 +    }
 +
 +    @Override
 +    public String[] mimeTypesSupported() {
 +        return new String[]{MIME_TYPE, SerTokens.MIME_JSON};
 +    }
 +
 +    @Override
 +    GraphSONMapper.Builder configureBuilder(final GraphSONMapper.Builder builder) {
 +        // already set to 2.0 in AbstractGraphSONMessageSerializerV2d0
 +        return builder.typeInfo(TypeInfo.PARTIAL_TYPES).addCustomModule(new GremlinServerModule());
 +    }
 +
 +    @Override
 +    byte[] obtainHeader() {
 +        return header;
 +    }
 +
 +    @Override
 +    public ResponseMessage deserializeResponse(final String msg) throws SerializationException {
 +        try {
 +            return mapper.readValue(msg, ResponseMessage.class);
 +        } catch (Exception ex) {
 +            logger.warn("Response [{}] could not be deserialized by {}.", msg, AbstractGraphSONMessageSerializerV2d0.class.getName());
 +            throw new SerializationException(ex);
 +        }
 +    }
 +
 +    @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) {
 +            logger.warn("Response [{}] could not be serialized by {}.", responseMessage.toString(), AbstractGraphSONMessageSerializerV2d0.class.getName());
 +            throw new SerializationException(ex);
 +        }
 +    }
 +
 +    @Override
 +    public RequestMessage deserializeRequest(final String msg) throws SerializationException {
 +        try {
 +            return mapper.readValue(msg, RequestMessage.class);
 +        } catch (Exception ex) {
 +            logger.warn("Request [{}] could not be deserialized by {}.", msg, AbstractGraphSONMessageSerializerV2d0.class.getName());
 +            throw new SerializationException(ex);
 +        }
 +    }
 +
 +    @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) {
 +            logger.warn("Request [{}] could not be serialized by {}.", requestMessage.toString(), AbstractGraphSONMessageSerializerV2d0.class.getName());
 +            throw new SerializationException(ex);
 +        }
 +    }
 +}
diff --cc gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV3d0.java
index acdbffd8f3,0000000000..8021392f3c
mode 100644,000000..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
@@@ -1,137 -1,0 +1,138 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + * http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.tinkerpop.gremlin.util.ser;
 +
++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;
 +import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion;
 +import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONXModuleV3d0;
 +import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
 +import org.slf4j.Logger;
 +import org.slf4j.LoggerFactory;
 +
 +import java.nio.ByteBuffer;
 +
 +/**
 + * Serialize results to JSON with version 3.0.x schema and the extended module.
 + *
 + * @author Stephen Mallette (http://stephen.genoprime.com)
 + */
 +public final class GraphSONMessageSerializerV3d0 extends AbstractGraphSONMessageSerializerV2d0 implements MessageTextSerializer<ObjectMapper> {
 +    private static final Logger logger = LoggerFactory.getLogger(GraphSONMessageSerializerV3d0.class);
 +    private static final String MIME_TYPE = SerTokens.MIME_GRAPHSON_V3D0;
 +
 +    private static byte[] header;
 +
 +    static {
 +        final ByteBuffer buffer = ByteBuffer.allocate(MIME_TYPE.length() + 1);
 +        buffer.put((byte) MIME_TYPE.length());
 +        buffer.put(MIME_TYPE.getBytes());
 +        header = buffer.array();
 +    }
 +
 +    /**
 +     * Creates a default GraphSONMessageSerializer.
 +     * <p>
 +     * By default this will internally instantiate a {@link GraphSONMapper} and register
 +     * a {@link GremlinServerModule} and {@link GraphSONXModuleV3d0} to the mapper.
 +     *
 +     * @see #GraphSONMessageSerializerV3d0(GraphSONMapper.Builder)
 +     */
 +    public GraphSONMessageSerializerV3d0() {
 +        super();
 +    }
 +
 +    /**
 +     * Create a GraphSONMessageSerializer from a {@link GraphSONMapper}. Deprecated, use
 +     * {@link #GraphSONMessageSerializerV3d0(GraphSONMapper.Builder)} instead.
 +     */
 +    @Deprecated
 +    public GraphSONMessageSerializerV3d0(final GraphSONMapper mapper) {
 +        super(mapper);
 +    }
 +
 +    /**
 +     * Create a GraphSONMessageSerializer with a provided {@link GraphSONMapper.Builder}.
 +     *
 +     * Note that to make this mapper usable in the context of request messages and responses,
 +     * this method will automatically register a {@link GremlinServerModule} to the provided
 +     * mapper.
 +     */
 +    public GraphSONMessageSerializerV3d0(final GraphSONMapper.Builder mapperBuilder) {
 +        super(mapperBuilder);
 +    }
 +
 +    @Override
 +    public String[] mimeTypesSupported() {
 +        return new String[]{MIME_TYPE, SerTokens.MIME_JSON};
 +    }
 +
 +    @Override
 +    GraphSONMapper.Builder configureBuilder(final GraphSONMapper.Builder builder) {
 +        // override the 2.0 in AbstractGraphSONMessageSerializerV2d0
 +        return builder.version(GraphSONVersion.V3_0).addCustomModule(new GremlinServerModule());
 +    }
 +
 +    @Override
 +    byte[] obtainHeader() {
 +        return header;
 +    }
 +
 +    @Override
 +    public ResponseMessage deserializeResponse(final String msg) throws SerializationException {
 +        try {
 +            return mapper.readValue(msg, ResponseMessage.class);
 +        } catch (Exception ex) {
 +            logger.warn(String.format("Response [%s] could not be deserialized by %s.", msg, GraphSONMessageSerializerV3d0.class.getName()), ex);
 +            throw new SerializationException(ex);
 +        }
 +    }
 +
 +    @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) {
 +            logger.warn(String.format("Response [%s] could not be serialized by %s.", responseMessage.toString(), GraphSONMessageSerializerV3d0.class.getName()), ex);
 +            throw new SerializationException(ex);
 +        }
 +    }
 +
 +    @Override
 +    public RequestMessage deserializeRequest(final String msg) throws SerializationException {
 +        try {
 +            return mapper.readValue(msg, RequestMessage.class);
 +        } catch (Exception ex) {
 +            logger.warn(String.format("Request [%s] could not be deserialized by %s.", msg, GraphSONMessageSerializerV3d0.class.getName()), ex);
 +            throw new SerializationException(ex);
 +        }
 +    }
 +
 +    @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) {
 +            logger.warn(String.format("Request [%s] could not be serialized by %s.", requestMessage.toString(), GraphSONMessageSerializerV3d0.class.getName()), ex);
 +            throw new SerializationException(ex);
 +        }
 +    }
 +}
diff --cc gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/MessageTextSerializer.java
index d81af2bc47,0000000000..7d46aabafb
mode 100644,000000..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
@@@ -1,41 -1,0 +1,42 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + * http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.tinkerpop.gremlin.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;
 +
 +/**
 + * An extension to the MessageSerializer interface that allows a format to be compatible with text-based
 + * websocket messages.  This interface is for internal purposes only.  Implementers who have mapper serialization
 + * needs should NOT implement this interface as it will not be used.  Gremlin Server only supports plain JSON
 + * for text-based requests.
 + *
 + * @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;
 +
 +    public ResponseMessage deserializeResponse(final String msg) throws SerializationException;
 +}
diff --cc gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV1d0Test.java
index 8e45448727,0000000000..d5d3d24ebe
mode 100644,000000..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
@@@ -1,510 -1,0 +1,512 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + * http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.tinkerpop.gremlin.util.ser;
 +
++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;
 +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 +import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
 +import org.apache.tinkerpop.gremlin.structure.Edge;
 +import org.apache.tinkerpop.gremlin.structure.Graph;
 +import org.apache.tinkerpop.gremlin.structure.Property;
 +import org.apache.tinkerpop.gremlin.structure.Vertex;
 +import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 +import org.apache.tinkerpop.gremlin.structure.io.AbstractIoRegistry;
 +import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONIo;
 +import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONTokens;
 +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.JsonNode;
 +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.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.IOException;
 +import java.util.ArrayList;
 +import java.util.Arrays;
 +import java.util.Collections;
 +import java.util.Date;
 +import java.util.HashMap;
 +import java.util.Map;
 +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.fail;
 +
 +/**
 + * These tests focus on message serialization and not "result" serialization as test specific to results (e.g.
 + * vertices, edges, annotated values, etc.) are handled in the IO packages.
 + *
 + * @author Stephen Mallette (http://stephen.genoprime.com)
 + */
 +public class GraphSONMessageSerializerV1d0Test {
 +
 +    public static final GraphSONMessageSerializerV1d0 SERIALIZER = new GraphSONMessageSerializerV1d0();
 +    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 {
 +        final GraphSONMessageSerializerV1d0 serializer = new GraphSONMessageSerializerV1d0();
 +        final Map<String, Object> config = new HashMap<String, Object>() {{
 +            put(AbstractMessageSerializer.TOKEN_IO_REGISTRIES, Arrays.asList(ColorIoRegistry.class.getName()));
 +        }};
 +
 +        serializer.configure(config, null);
 +
 +        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));
 +    }
 +
 +    @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());
 +        assertEquals(NullNode.getInstance(), json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA));
 +    }
 +
 +    @Test
 +    public void shouldSerializeToJsonIterable() throws Exception {
 +        final ArrayList<FunObject> funList = new ArrayList<>();
 +        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);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
 +
 +        assertEquals(2, converted.size());
 +
 +        assertEquals("x", converted.get(0).asText());
 +        assertEquals("y", converted.get(1).asText());
 +    }
 +
 +    @Test
 +    public void shouldSerializeToJsonIterator() throws Exception {
 +        final ArrayList<FunObject> funList = new ArrayList<>();
 +        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);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
 +
 +        assertEquals(2, converted.size());
 +
 +        assertEquals("x", converted.get(0).asText());
 +        assertEquals("y", converted.get(1).asText());
 +    }
 +
 +    @Test
 +    public void shouldSerializeToJsonIteratorNullElement() throws Exception {
 +
 +        final ArrayList<FunObject> funList = new ArrayList<>();
 +        funList.add(new FunObject("x"));
 +        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);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
 +
 +        assertEquals(3, converted.size());
 +
 +        assertEquals("x", converted.get(0).asText());
 +        assertEquals(NullNode.getInstance(), converted.get(1));
 +        assertEquals("y", converted.get(2).asText());
 +    }
 +
 +    @Test
 +    public void shouldSerializeToJsonMap() throws Exception {
 +        final Map<String, Object> map = new HashMap<>();
 +        final Map<String, String> innerMap = new HashMap<>();
 +        innerMap.put("a", "b");
 +
 +        map.put("x", new FunObject("x"));
 +        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);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        final JsonNode jsonObject = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
 +
 +        assertNotNull(jsonObject);
 +        assertEquals("some", jsonObject.get("y").asText());
 +        assertEquals("x", jsonObject.get("x").asText());
 +
 +        final JsonNode innerJsonObject = jsonObject.get("z");
 +        assertNotNull(innerJsonObject);
 +        assertEquals("b", innerJsonObject.get("a").asText());
 +    }
 +
 +    @Test
 +    public void shouldShouldSerializeMapEntries() throws Exception {
 +        final Graph graph = TinkerGraph.open();
 +        final Vertex v1 = graph.addVertex();
 +        final Date d = new Date();
 +
 +        final Map<Object, Object> map = new HashMap<>();
 +        map.put("x", 1);
 +        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);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        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").asInt());
 +            else if (e.has(v1.id().toString()))
 +                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
 +                fail("Map entries contains a key that is not part of what was serialized");
 +        });
 +    }
 +
 +    @Test
 +    public void shouldSerializeEdge() throws Exception {
 +        final Graph g = TinkerGraph.open();
 +        final Vertex v1 = g.addVertex();
 +        final Vertex v2 = g.addVertex();
 +        final Edge e = v1.addEdge("test", v2);
 +        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);
 +
 +        assertNotNull(json);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
 +
 +        assertNotNull(converted);
 +        assertEquals(1, converted.size());
 +
 +        final JsonNode edgeAsJson = converted.get(0);
 +        assertNotNull(edgeAsJson);
 +
 +        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").asInt());
 +    }
 +
 +    @Test
 +    public void shouldSerializeEdgeProperty() throws Exception {
 +        final Graph g = TinkerGraph.open();
 +        final Vertex v1 = g.addVertex();
 +        final Vertex v2 = g.addVertex();
 +        final Edge e = v1.addEdge("test", v2);
 +        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);
 +
 +        assertNotNull(json);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
 +
 +        assertNotNull(converted);
 +        assertEquals(1, converted.size());
 +
 +        final JsonNode propertyAsJson = converted.get(0);
 +        assertNotNull(propertyAsJson);
 +
 +        assertEquals(123, propertyAsJson.get("value").asInt());
 +    }
 +
 +    @Test
 +    public void shouldSerializeToJsonIteratorWithEmbeddedMap() throws Exception {
 +        final Graph g = TinkerGraph.open();
 +        final Vertex v = g.addVertex();
 +        final Map<String, Object> map = new HashMap<>();
 +        map.put("x", 500);
 +        map.put("y", "some");
 +
 +        final ArrayList<Object> friends = new ArrayList<>();
 +        friends.add("x");
 +        friends.add(5);
 +        friends.add(map);
 +
 +        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);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
 +
 +        assertNotNull(converted);
 +        assertEquals(1, converted.size());
 +
 +        final JsonNode vertexAsJson = converted.get(0);
 +        assertNotNull(vertexAsJson);
 +
 +        final JsonNode properties = vertexAsJson.get(GraphSONTokens.PROPERTIES);
 +        assertNotNull(properties);
 +        assertEquals(1, properties.size());
 +
 +        final JsonNode friendProperties = properties.get("friends");
 +        assertEquals(1, friendProperties.size());
 +        final JsonNode friendsProperty = friendProperties.get(0);
 +        assertNotNull(friendsProperty);
 +        assertEquals(3, friends.size());
 +
 +        final String object1 = friendsProperty.get(GraphSONTokens.VALUE).get(0).asText();
 +        assertEquals("x", object1);
 +
 +        final int object2 = friendsProperty.get(GraphSONTokens.VALUE).get(1).asInt();
 +        assertEquals(5, object2);
 +
 +        final JsonNode object3 = friendsProperty.get(GraphSONTokens.VALUE).get(2);
 +        assertEquals(500, object3.get("x").asInt());
 +        assertEquals("some", object3.get("y").asText());
 +    }
 +
 +    @Test
 +    public void shouldSerializeToJsonMapWithElementForKey() throws Exception {
 +        final TinkerGraph graph = TinkerFactory.createClassic();
 +        final GraphTraversalSource g = graph.traversal();
 +        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);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
 +
 +        assertNotNull(converted);
 +
 +        // 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").asInt());
 +    }
 +
 +    @Test
 +    public void shouldDeserializeRequestNicelyWithNoArgs() throws Exception {
 +        final UUID request = UUID.fromString("011CFEE9-F640-4844-AC93-034448AC0E80");
 +        final RequestMessage m = SERIALIZER.deserializeRequest(String.format("{\"requestId\":\"%s\",\"op\":\"eval\"}", request));
 +        assertEquals(request, m.getRequestId());
 +        assertEquals("eval", m.getOp());
 +        assertNotNull(m.getArgs());
 +        assertEquals(0, m.getArgs().size());
 +    }
 +
 +    @Test
 +    public void shouldDeserializeRequestNicelyWithArgs() throws Exception {
 +        final UUID request = UUID.fromString("011CFEE9-F640-4844-AC93-034448AC0E80");
 +        final RequestMessage m = SERIALIZER.deserializeRequest(String.format("{\"requestId\":\"%s\",\"op\":\"eval\",\"args\":{\"x\":\"y\"}}", request));
 +        assertEquals(request, m.getRequestId());
 +        assertEquals("eval", m.getOp());
 +        assertNotNull(m.getArgs());
 +        assertEquals("y", m.getArgs().get("x"));
 +    }
 +
 +    @Test(expected = SerializationException.class)
 +    public void shouldDeserializeRequestParseMessage() throws Exception {
 +        SERIALIZER.deserializeRequest("{\"requestId\":\"%s\",\"op\":\"eval\",\"args\":{\"x\":\"y\"}}");
 +    }
 +
 +    @Test
 +    public void shouldSerializeFullResponseMessage() throws Exception {
 +        final UUID id = UUID.randomUUID();
 +
 +        final Map<String, Object> metaData = new HashMap<>();
 +        metaData.put("test", "this");
 +        metaData.put("one", 1);
 +
 +        final Map<String, Object> attributes = new HashMap<>();
 +        attributes.put("test", "that");
 +        attributes.put("two", 2);
 +
 +        final ResponseMessage response = ResponseMessage.build(id)
 +                .responseMetaData(metaData)
 +                .code(ResponseStatusCode.SUCCESS)
 +                .result("some-result")
 +                .statusAttributes(attributes)
 +                .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());
 +        assertEquals("this", deserialized.getResult().getMeta().get("test"));
 +        assertEquals(1, deserialized.getResult().getMeta().get("one"));
 +        assertEquals("some-result", deserialized.getResult().getData());
 +        assertEquals("that", deserialized.getStatus().getAttributes().get("test"));
 +        assertEquals(2, deserialized.getStatus().getAttributes().get("two"));
 +        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);
++        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 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());
++        final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(t).create(), allocator);
 +
 +        final JsonNode json = mapper.readTree(results);
 +
 +        assertNotNull(json);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
 +        assertNotNull(converted);
 +        
 +        //check the first object and it's properties
 +        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());
 +        
 +        //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 {
 +        private String val;
 +
 +        public FunObject(String val) {
 +            this.val = val;
 +        }
 +
 +        public String toString() {
 +            return this.val;
 +        }
 +    }
 +
 +    public static class ColorIoRegistry extends AbstractIoRegistry {
 +        public ColorIoRegistry() {
 +            register(GraphSONIo.class, null, new ColorSimpleModule());
 +        }
 +    }
 +
 +    public static class ColorSimpleModule extends SimpleModule {
 +        public ColorSimpleModule() {
 +            super("color-fun");
 +            addSerializer(Color.class, new ColorSerializer());
 +
 +        }
 +    }
 +
 +    public static class ColorSerializer extends StdSerializer<Color> {
 +        public ColorSerializer() {
 +            super(Color.class);
 +        }
 +
 +        @Override
 +        public void serialize(final Color color, final JsonGenerator jsonGenerator,
 +                              final SerializerProvider serializerProvider) throws IOException, JsonGenerationException {
 +            jsonGenerator.writeBoolean(color.equals(Color.RED));
 +        }
 +    }
 +}
diff --cc gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/GraphSONMessageSerializerV2d0Test.java
index a091006cfd,0000000000..2a0bf47e14
mode 100644,000000..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
@@@ -1,616 -1,0 +1,616 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + * http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.tinkerpop.gremlin.util.ser;
 +
 +import io.netty.buffer.ByteBuf;
 +import io.netty.buffer.ByteBufAllocator;
 +import io.netty.buffer.UnpooledByteBufAllocator;
 +import org.apache.tinkerpop.gremlin.util.MessageSerializer;
 +import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 +import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
 +import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 +import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
 +import org.apache.tinkerpop.gremlin.structure.Edge;
 +import org.apache.tinkerpop.gremlin.structure.Graph;
 +import org.apache.tinkerpop.gremlin.structure.Property;
 +import org.apache.tinkerpop.gremlin.structure.Vertex;
 +import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 +import org.apache.tinkerpop.gremlin.structure.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;
 +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.Test;
 +
 +import java.awt.Color;
 +import java.io.ByteArrayOutputStream;
 +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;
 +
 +/**
 + * These tests focus on message serialization and not "result" serialization as test specific to results (e.g.
 + * vertices, edges, annotated values, etc.) are handled in the IO packages.
 + *
 + * @author Stephen Mallette (http://stephen.genoprime.com)
 + */
 +@SuppressWarnings("unchecked")
 +public class GraphSONMessageSerializerV2d0Test {
 +
 +    public static final GraphSONMessageSerializerV2d0 SERIALIZER = new GraphSONMessageSerializerV2d0();
 +    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;
 +
 +    @Test
 +    public void shouldConfigureIoRegistry() throws Exception {
 +        final GraphSONMessageSerializerV1d0 serializer = new GraphSONMessageSerializerV1d0();
 +        final Map<String, Object> config = new HashMap<String, Object>() {{
 +            put(AbstractMessageSerializer.TOKEN_IO_REGISTRIES, Arrays.asList(ColorIoRegistry.class.getName()));
 +        }};
 +
 +        serializer.configure(config, null);
 +
 +        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));
 +    }
 +
 +    @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());
 +        assertEquals(NullNode.getInstance(), json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA));
 +    }
 +
 +    @Test
 +    public void shouldSerializeToJsonIterable() throws Exception {
 +        final ArrayList<FunObject> funList = new ArrayList<>();
 +        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);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
 +
 +        assertEquals(2, converted.size());
 +
 +        assertEquals("x", converted.get(0).asText());
 +        assertEquals("y", converted.get(1).asText());
 +    }
 +
 +    @Test
 +    public void shouldSerializeToJsonIterator() throws Exception {
 +        final ArrayList<FunObject> funList = new ArrayList<>();
 +        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);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
 +
 +        assertEquals(2, converted.size());
 +
 +        assertEquals("x", converted.get(0).asText());
 +        assertEquals("y", converted.get(1).asText());
 +    }
 +
 +    @Test
 +    public void shouldSerializeToJsonIteratorNullElement() throws Exception {
 +
 +        final ArrayList<FunObject> funList = new ArrayList<>();
 +        funList.add(new FunObject("x"));
 +        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);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
 +
 +        assertEquals(3, converted.size());
 +
 +        assertEquals("x", converted.get(0).asText());
 +        assertEquals(NullNode.getInstance(), converted.get(1));
 +        assertEquals("y", converted.get(2).asText());
 +    }
 +
 +    @Test
 +    public void shouldSerializeToJsonMap() throws Exception {
 +        final Map<String, Object> map = new HashMap<>();
 +        final Map<String, String> innerMap = new HashMap<>();
 +        innerMap.put("a", "b");
 +
 +        map.put("x", new FunObject("x"));
 +        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);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        final JsonNode jsonObject = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
 +
 +        assertNotNull(jsonObject);
 +        assertEquals("some", jsonObject.get("y").asText());
 +        assertEquals("x", jsonObject.get("x").asText());
 +
 +        final JsonNode innerJsonObject = jsonObject.get("z");
 +        assertNotNull(innerJsonObject);
 +        assertEquals("b", innerJsonObject.get("a").asText());
 +    }
 +
 +    @Test
 +    public void shouldShouldSerializeMapEntries() throws Exception {
 +        final Graph graph = TinkerGraph.open();
 +        final Vertex v1 = graph.addVertex();
 +        final Date d = new Date();
 +
 +        final Map<Object, Object> map = new HashMap<>();
 +        map.put("x", 1);
 +        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);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        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());
 +            else if (e.has(v1.id().toString()))
 +                assertEquals(100, e.get(v1.id().toString()).get(GraphSONTokens.VALUEPROP).asInt());
 +            else if (e.has(StdDateFormat.instance.format(d)))
 +                assertEquals("test", e.get(StdDateFormat.instance.format(d)).asText());
 +            else
 +                fail("Map entries contains a key that is not part of what was serialized");
 +        });
 +    }
 +
 +    @Test
 +    public void shouldSerializeEdge() throws Exception {
 +        final Graph g = TinkerGraph.open();
 +        final Vertex v1 = g.addVertex();
 +        final Vertex v2 = g.addVertex();
 +        final Edge e = v1.addEdge("test", v2);
 +        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);
 +
 +        assertNotNull(json);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
 +
 +        assertNotNull(converted);
 +        assertEquals(1, converted.size());
 +
 +        final JsonNode edgeAsJson = converted.get(0).get(GraphSONTokens.VALUEPROP);
 +        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(e.label(), edgeAsJson.get(GraphSONTokens.LABEL).asText());
 +
 +        final JsonNode properties = edgeAsJson.get(GraphSONTokens.PROPERTIES);
 +        assertNotNull(properties);
 +        assertEquals(123, properties.get("abc").get(GraphSONTokens.VALUEPROP).get("value").get(GraphSONTokens.VALUEPROP).asInt());
 +    }
 +
 +    @Test
 +    public void shouldSerializeEdgeProperty() throws Exception {
 +        final Graph g = TinkerGraph.open();
 +        final Vertex v1 = g.addVertex();
 +        final Vertex v2 = g.addVertex();
 +        final Edge e = v1.addEdge("test", v2);
 +        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);
 +
 +        assertNotNull(json);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
 +
 +        assertNotNull(converted);
 +        assertEquals(1, converted.size());
 +
 +        final JsonNode propertyAsJson = converted.get(0);
 +        assertNotNull(propertyAsJson);
 +
 +        assertEquals(123, propertyAsJson.get(GraphSONTokens.VALUEPROP).get("value").get(GraphSONTokens.VALUEPROP).asInt());
 +    }
 +
 +    @Test
 +    public void shouldSerializeToJsonIteratorWithEmbeddedMap() throws Exception {
 +        final Graph g = TinkerGraph.open();
 +        final Vertex v = g.addVertex();
 +        final Map<String, Object> map = new HashMap<>();
 +        map.put("x", 500);
 +        map.put("y", "some");
 +
 +        final ArrayList<Object> friends = new ArrayList<>();
 +        friends.add("x");
 +        friends.add(5);
 +        friends.add(map);
 +
 +        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);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
 +
 +        assertNotNull(converted);
 +        assertEquals(1, converted.size());
 +
 +        final JsonNode vertexAsJson = converted.get(0).get(GraphSONTokens.VALUEPROP);
 +        assertNotNull(vertexAsJson);
 +
 +        final JsonNode properties = vertexAsJson.get(GraphSONTokens.PROPERTIES);
 +        assertNotNull(properties);
 +        assertEquals(1, properties.size());
 +
 +        final JsonNode friendProperties = properties.get("friends");
 +        assertEquals(1, friendProperties.size());
 +        final JsonNode friendsProperty = friendProperties.get(0).get(GraphSONTokens.VALUEPROP).get(GraphSONTokens.VALUE);
 +        assertNotNull(friendsProperty);
 +        assertEquals(3, friendsProperty.size());
 +
 +        final String object1 = friendsProperty.get(0).asText();
 +        assertEquals("x", object1);
 +
 +        final int object2 = friendsProperty.get(1).get(GraphSONTokens.VALUEPROP).asInt();
 +        assertEquals(5, object2);
 +
 +        final JsonNode object3 = friendsProperty.get(2);
 +        assertEquals(500, object3.get("x").get(GraphSONTokens.VALUEPROP).asInt());
 +        assertEquals("some", object3.get("y").asText());
 +    }
 +
 +    @Test
 +    public void shouldSerializeToJsonMapWithElementForKey() throws Exception {
 +        final TinkerGraph graph = TinkerFactory.createClassic();
 +        final GraphTraversalSource g = graph.traversal();
 +        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);
 +        assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
 +        final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
 +
 +        assertNotNull(converted);
 +
 +        // 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());
 +    }
 +
 +    @Test
 +    public void shouldDeserializeRequestNicelyWithNoArgs() throws Exception {
 +        final UUID request = UUID.fromString("011CFEE9-F640-4844-AC93-034448AC0E80");
 +        final RequestMessage m = SERIALIZER.deserializeRequest(String.format("{\"requestId\":\"%s\",\"op\":\"eval\"}", request));
 +        assertEquals(request, m.getRequestId());
 +        assertEquals("eval", m.getOp());
 +        assertNotNull(m.getArgs());
 +        assertEquals(0, m.getArgs().size());
 +    }
 +
 +    @Test
 +    public void shouldDeserializeRequestNicelyWithArgs() throws Exception {
 +        final UUID request = UUID.fromString("011CFEE9-F640-4844-AC93-034448AC0E80");
 +        final RequestMessage m = SERIALIZER.deserializeRequest(String.format("{\"requestId\":\"%s\",\"op\":\"eval\",\"args\":{\"x\":\"y\"}}", request));
 +        assertEquals(request, m.getRequestId());
 +        assertEquals("eval", m.getOp());
 +        assertNotNull(m.getArgs());
 +        assertEquals("y", m.getArgs().get("x"));
 +    }
 +
 +    @Test(expected = SerializationException.class)
 +    public void shouldDeserializeRequestParseMessage() throws Exception {
 +        SERIALIZER.deserializeRequest("{\"requestId\":\"%s\",\"op\":\"eval\",\"args\":{\"x\":\"y\"}}");
 +    }
 +
 +    @Test
 +    public void shouldSerializeFullResponseMessage() throws Exception {
 +        final UUID id = UUID.randomUUID();
 +
 +        final Map<String, Object> metaData = new HashMap<>();
 +        metaData.put("test", "this");
 +        metaData.put("one", 1);
 +
 +        final Map<String, Object> attributes = new HashMap<>();
 +        attributes.put("test", "that");
 +        attributes.put("two", 2);
 +
 +        final ResponseMessage response = ResponseMessage.build(id)
 +                .responseMetaData(metaData)
 +                .code(ResponseStatusCode.SUCCESS)
 +                .result("some-result")
 +                .statusAttributes(attributes)
 +                .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());
 +        assertEquals("this", deserialized.getResult().getMeta().get("test"));
 +        assertEquals(1, deserialized.getResult().getMeta().get("one"));
 +        assertEquals("some-result", deserialized.getResult().getData());
 +        assertEquals("that", deserialized.getStatus().getAttributes().get("test"));
 +        assertEquals(2, deserialized.getStatus().getAttributes().get("two"));
 +        assertEquals(ResponseStatusCode.SUCCESS.getValue(), deserialized.getStatus().getCode().getValue());
 +        assertEquals("worked", deserialized.getStatus().getMessage());
 +    }
 +    
 +    @Test
 +    public void shouldSerializeToTreeJson() 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());
++        final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(t).create(), allocator);
 +
 +        final JsonNode json = mapper.readTree(results);
 +
 +        assertNotNull(json);
 +        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");
 +        }};
 +        
 +        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.util.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);
 +    }
 +
 +    private class FunObject {
 +        private String val;
 +
 +        public FunObject(String val) {
 +            this.val = val;
 +        }
 +
 +        public String toString() {
 +            return this.val;
 +        }
 +    }
 +
 +    public static class ColorIoRegistry extends AbstractIoRegistry {
 +        public ColorIoRegistry() {
 +            register(GraphSONIo.class, null, new ColorSimpleModule());
 +        }
 +    }
 +
 +    public static class ColorSimpleModule extends SimpleModule {
 +        public ColorSimpleModule() {
 +            super("color-fun");
 +            addSerializer(Color.class, new ColorSerializer());
 +
 +        }
 +    }
 +
 +    public static class ColorSerializer extends StdSerializer<Color> {
 +        public ColorSerializer() {
 +            super(Color.class);
 +        }
 +
 +        @Override
 +        public void serialize(final Color color, final JsonGenerator jsonGenerator,
 +                              final SerializerProvider serializerProvider) throws IOException, JsonGenerationException {
 +            jsonGenerator.writeBoolean(color.equals(Color.RED));
 +        }
 +    }
 +}
diff --cc gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryMessageSerializerV1Test.java
index 8813491422,0000000000..c4b486f0fe
mode 100644,000000..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
@@@ -1,198 -1,0 +1,235 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + * http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.tinkerpop.gremlin.util.ser.binary;
 +
 +import io.netty.buffer.ByteBuf;
 +import io.netty.buffer.ByteBufAllocator;
 +import org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 +import org.apache.tinkerpop.gremlin.util.message.ResponseMessage;
 +import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 +import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
 +import org.apache.tinkerpop.gremlin.util.ser.SerializationException;
 +import org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry;
 +import org.junit.Test;
 +
 +import java.util.Collections;
 +import java.util.HashMap;
 +import java.util.Map;
 +import java.util.UUID;
 +import java.util.concurrent.atomic.AtomicInteger;
 +
 +import static org.apache.tinkerpop.gremlin.util.MockitoHamcrestMatcherAdapter.reflectionEquals;
 +import static org.junit.Assert.assertEquals;
 +import static org.hamcrest.MatcherAssert.assertThat;
 +
 +public class GraphBinaryMessageSerializerV1Test {
 +    private final ByteBufAllocator allocator = ByteBufAllocator.DEFAULT;
 +    private final GraphBinaryMessageSerializerV1 serializer = new GraphBinaryMessageSerializerV1();
 +
 +    @Test
 +    public void shouldSerializeAndDeserializeRequest() throws SerializationException {
 +        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));
 +    }
 +
 +    @Test
 +    public void shouldSerializeAndDeserializeRequestWithoutArgs() throws SerializationException {
 +        final RequestMessage request = RequestMessage.build("op1")
 +                .processor("proc1")
 +                .overrideRequestId(UUID.randomUUID())
 +                .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));
 +    }
 +
 +    @Test
 +    public void shouldSerializeAndDeserializeRequestWithUnsetProcessor() throws SerializationException {
 +        final RequestMessage request = RequestMessage.build("op1")
 +                .overrideRequestId(UUID.randomUUID())
 +                .addArg("k", 1)
 +                .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));
 +    }
 +
 +    @Test
 +    public void shouldSerializeAndDeserializeResponse() throws SerializationException {
 +        final ResponseMessage response = ResponseMessage.build(UUID.randomUUID())
 +                .code(ResponseStatusCode.SUCCESS)
 +                .statusMessage("Found")
 +                .statusAttribute("k1", 1)
 +                .result("This is a fine message with a string")
 +                .create();
 +
 +        final ByteBuf buffer = serializer.serializeResponseAsBinary(response, allocator);
 +        final ResponseMessage deserialized = serializer.deserializeResponse(buffer);
 +        assertResponseEquals(response, deserialized);
 +    }
 +
 +    @Test
 +    public void shouldSerializeAndDeserializeResponseWithoutStatusMessage() throws SerializationException {
 +        final ResponseMessage response = ResponseMessage.build(UUID.randomUUID())
 +                .code(ResponseStatusCode.SUCCESS)
 +                .statusAttribute("k1", 1)
 +                .result(123.3)
 +                .create();
 +
 +        final ByteBuf buffer = serializer.serializeResponseAsBinary(response, allocator);
 +        final ResponseMessage deserialized = serializer.deserializeResponse(buffer);
 +        assertResponseEquals(response, deserialized);
 +    }
 +
 +    @Test
 +    public void shouldSerializeAndDeserializeResponseWithoutStatusAttributes() throws SerializationException {
 +        final ResponseMessage response = ResponseMessage.build(UUID.randomUUID())
 +                .code(ResponseStatusCode.SUCCESS)
 +                .result(123.3)
 +                .create();
 +
 +        final ByteBuf buffer = serializer.serializeResponseAsBinary(response, allocator);
 +        final ResponseMessage deserialized = serializer.deserializeResponse(buffer);
 +        assertResponseEquals(response, deserialized);
 +    }
 +
 +    @Test
 +    public void shouldSerializeAndDeserializeResponseWithoutResult() throws SerializationException {
 +        final ResponseMessage response = ResponseMessage.build(UUID.randomUUID())
 +                .code(ResponseStatusCode.SERVER_ERROR)
 +                .statusMessage("Something happened on the server")
 +                .create();
 +
 +        final ByteBuf buffer = serializer.serializeResponseAsBinary(response, allocator);
 +        final ResponseMessage deserialized = serializer.deserializeResponse(buffer);
 +        assertResponseEquals(response, deserialized);
 +    }
 +
 +    @Test
 +    public void shouldSupportConfigurationOfRegistryBuilder() {
 +        final GraphBinaryMessageSerializerV1 serializer = new GraphBinaryMessageSerializerV1();
 +        final Map<String, Object> config = new HashMap<>();
 +        int counter = SampleTypeSerializerRegistryBuilder.createCounter.get();
 +
 +        config.put(GraphBinaryMessageSerializerV1.TOKEN_BUILDER, "org.apache.tinkerpop.gremlin.util.ser.binary.GraphBinaryMessageSerializerV1Test$SampleTypeSerializerRegistryBuilder");
 +        serializer.configure(config, null);
 +
 +        counter = SampleTypeSerializerRegistryBuilder.createCounter.get() - counter;
 +        // There should be a call to `create()`
 +        assertEquals(1, counter);
 +    }
 +
 +    @Test(expected = IllegalStateException.class)
 +    public void shouldThrowWhenConfigurationOfRegistryBuilderFails() {
 +        final GraphBinaryMessageSerializerV1 serializer = new GraphBinaryMessageSerializerV1();
 +        final Map<String, Object> config = new HashMap<>();
 +        config.put(GraphBinaryMessageSerializerV1.TOKEN_BUILDER, "org.apache.tinkerpop.gremlin.util.ser.binary.NonExistentClass");
 +
 +        serializer.configure(config, null);
 +    }
 +
 +    @Test
 +    public void shouldToStringSerialize() 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 ByteBuf buffer = serializer.serializeResponseAsBinary(messageWithUnexpectedType, allocator);
 +        final ResponseMessage deserialized = serializer.deserializeResponse(buffer);
 +
 +        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
 +        assertEquals(expected.getStatus().getCode(), actual.getStatus().getCode());
 +        assertEquals(expected.getStatus().getMessage(), actual.getStatus().getMessage());
 +        assertEquals(expected.getStatus().getAttributes(), actual.getStatus().getAttributes());
 +        // Result
 +        assertEquals(expected.getResult().getData(), actual.getResult().getData());
 +        assertEquals(expected.getResult().getMeta(), actual.getResult().getMeta());
 +    }
 +
 +    public static class SampleTypeSerializerRegistryBuilder extends TypeSerializerRegistry.Builder {
 +        public static AtomicInteger createCounter = new AtomicInteger();
 +
 +        @Override
 +        public TypeSerializerRegistry create() {
 +            createCounter.incrementAndGet();
 +            return super.create();
 +        }
 +    }
 +}