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 2017/04/06 21:57:09 UTC

tinkerpop git commit: TINKERPOP-1044 Additional error data to Gremlin Server responses

Repository: tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1044 [created] b29bab0ac


TINKERPOP-1044 Additional error data to Gremlin Server responses

Applies to all protocols: http, nio, and websocket. Added stack trace and exception hierarchy. Deprecated the "Exception-Class" in the http protocol.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/b29bab0a
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/b29bab0a
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/b29bab0a

Branch: refs/heads/TINKERPOP-1044
Commit: b29bab0acada54aa525184935d96b41f9cf0854b
Parents: 95d3efc
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Thu Apr 6 17:55:39 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Thu Apr 6 17:55:39 2017 -0400

----------------------------------------------------------------------
 .../tinkerpop/gremlin/driver/Handler.java       | 11 ++++--
 .../apache/tinkerpop/gremlin/driver/Tokens.java |  3 ++
 .../driver/exception/ResponseException.java     | 20 +++++++++++
 .../gremlin/driver/message/ResponseMessage.java | 19 ++++++++++
 .../gremlin/driver/ResultQueueTest.java         |  2 --
 .../handler/GremlinResponseFrameEncoder.java    |  6 ++--
 .../handler/HttpGremlinEndpointHandler.java     |  9 +++--
 .../gremlin/server/handler/IteratorHandler.java |  5 ++-
 .../handler/NioGremlinResponseEncoder.java      |  5 +--
 .../server/handler/OpExecutorHandler.java       |  1 +
 .../server/handler/OpSelectorHandler.java       |  4 ++-
 .../handler/WsGremlinResponseEncoder.java       |  5 +--
 .../server/op/AbstractEvalOpProcessor.java      | 31 +++++++++++-----
 .../gremlin/server/op/AbstractOpProcessor.java  |  5 +--
 .../op/traversal/TraversalOpProcessor.java      | 35 +++++++++++++-----
 .../gremlin/server/util/ExceptionHelper.java    | 38 ++++++++++++++++++++
 .../server/GremlinDriverIntegrateTest.java      |  5 +++
 .../server/GremlinServerHttpIntegrateTest.java  |  8 +++++
 18 files changed, 179 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b29bab0a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java
index 650bc2f..1bd0a3b 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java
@@ -235,8 +235,15 @@ final class Handler {
                     }
                 } else {
                     // this is a "success" but represents no results otherwise it is an error
-                    if (statusCode != ResponseStatusCode.NO_CONTENT)
-                        queue.markError(new ResponseException(response.getStatus().getCode(), response.getStatus().getMessage()));
+                    if (statusCode != ResponseStatusCode.NO_CONTENT) {
+                        final Map<String,Object> attributes = response.getStatus().getAttributes();
+                        final String stackTrace = attributes.containsKey(Tokens.STATUS_ATTRIBUTE_STACK_TRACE) ?
+                                (String) attributes.get(Tokens.STATUS_ATTRIBUTE_STACK_TRACE) : null;
+                        final List<String> exceptions = attributes.containsKey(Tokens.STATUS_ATTRIBUTE_EXCEPTIONS) ?
+                                (List<String>) attributes.get(Tokens.STATUS_ATTRIBUTE_EXCEPTIONS) : null;
+                        queue.markError(new ResponseException(response.getStatus().getCode(), response.getStatus().getMessage(),
+                                exceptions, stackTrace));
+                    }
                 }
 
                 // as this is a non-PARTIAL_CONTENT code - the stream is done

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b29bab0a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java
index fb577d7..9aee728 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Tokens.java
@@ -155,4 +155,7 @@ public final class Tokens {
     public static final String VAL_AGGREGATE_TO_SET = "set";
 
     public static final String VAL_TRAVERSAL_SOURCE_ALIAS = "g";
+
+    public static final String STATUS_ATTRIBUTE_EXCEPTIONS = "exceptions";
+    public static final String STATUS_ATTRIBUTE_STACK_TRACE = "stackTrace";
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b29bab0a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/exception/ResponseException.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/exception/ResponseException.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/exception/ResponseException.java
index 3ae4e75..800c2fc 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/exception/ResponseException.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/exception/ResponseException.java
@@ -20,18 +20,38 @@ package org.apache.tinkerpop.gremlin.driver.exception;
 
 import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
 
+import java.util.List;
+import java.util.Optional;
+
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public class ResponseException extends Exception {
     private ResponseStatusCode responseStatusCode;
+    private String remoteStackTrace = null;
+    private List<String> remoteExceptionHierarchy = null;
 
     public ResponseException(final ResponseStatusCode responseStatusCode, final String serverMessage) {
         super(serverMessage);
         this.responseStatusCode = responseStatusCode;
     }
 
+    public ResponseException(final ResponseStatusCode responseStatusCode, final String serverMessage,
+                             final List<String> remoteExceptionHierarchy, final String remoteStackTrace) {
+        this(responseStatusCode, serverMessage);
+        this.remoteExceptionHierarchy = remoteExceptionHierarchy;
+        this.remoteStackTrace = remoteStackTrace;
+    }
+
     public ResponseStatusCode getResponseStatusCode() {
         return responseStatusCode;
     }
+
+    public Optional<String> getRemoteStackTrace() {
+        return Optional.ofNullable(remoteStackTrace);
+    }
+
+    public Optional<List<String>> getRemoteExceptionHierarchy() {
+        return Optional.ofNullable(remoteExceptionHierarchy);
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b29bab0a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseMessage.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseMessage.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseMessage.java
index c5a00f6..f4126b1 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseMessage.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/message/ResponseMessage.java
@@ -18,7 +18,12 @@
  */
 package org.apache.tinkerpop.gremlin.driver.message;
 
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.tinkerpop.gremlin.driver.Tokens;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
+
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.UUID;
 
@@ -102,6 +107,20 @@ public final class ResponseMessage {
             return this;
         }
 
+        public Builder statusAttributeException(final Throwable ex) {
+            statusAttribute(Tokens.STATUS_ATTRIBUTE_EXCEPTIONS, IteratorUtils.asList(
+                    IteratorUtils.map(ExceptionUtils.getThrowableList(ex), t -> t.getClass().getName())));
+            statusAttribute(Tokens.STATUS_ATTRIBUTE_STACK_TRACE, ExceptionUtils.getFullStackTrace(ex));
+            return this;
+        }
+
+        public Builder statusAttribute(final String key, final Object value) {
+            if (this.attributes == Collections.EMPTY_MAP)
+                attributes = new HashMap<>();
+            attributes.put(key, value);
+            return this;
+        }
+
         public Builder result(final Object result) {
             this.result = result;
             return this;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b29bab0a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ResultQueueTest.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ResultQueueTest.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ResultQueueTest.java
index 67bbc48..a7e6066 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ResultQueueTest.java
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ResultQueueTest.java
@@ -37,8 +37,6 @@ import java.util.concurrent.atomic.AtomicInteger;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.greaterThan;
-import static org.hamcrest.core.IsCollectionContaining.hasItem;
-import static org.hamcrest.Matchers.contains;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b29bab0a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/GremlinResponseFrameEncoder.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/GremlinResponseFrameEncoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/GremlinResponseFrameEncoder.java
index d0f9d76..3aa8c36 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/GremlinResponseFrameEncoder.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/GremlinResponseFrameEncoder.java
@@ -20,11 +20,13 @@ package org.apache.tinkerpop.gremlin.server.handler;
 
 import com.codahale.metrics.Meter;
 import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
+import org.apache.tinkerpop.gremlin.driver.Tokens;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
 import org.apache.tinkerpop.gremlin.server.GremlinServer;
 import org.apache.tinkerpop.gremlin.server.op.session.Session;
+import org.apache.tinkerpop.gremlin.server.util.ExceptionHelper;
 import org.apache.tinkerpop.gremlin.server.util.MetricManager;
 import io.netty.channel.ChannelHandler;
 import io.netty.channel.ChannelHandlerContext;
@@ -91,10 +93,10 @@ public class GremlinResponseFrameEncoder extends MessageToMessageEncoder<Respons
         } catch (Exception ex) {
             errorMeter.mark();
             logger.warn("The result [{}] in the request {} could not be serialized and returned.", o.getResult(), o.getRequestId(), ex);
-            final String errorMessage = String.format("Error during serialization: %s",
-                    ex.getCause() != null ? ex.getCause().getMessage() : ex.getMessage());
+            final String errorMessage = String.format("Error during serialization: %s", ExceptionHelper.getMessageFromExceptionOrCause(ex));
             final ResponseMessage error = ResponseMessage.build(o.getRequestId())
                     .statusMessage(errorMessage)
+                    .statusAttributeException(ex)
                     .code(ResponseStatusCode.SERVER_ERROR_SERIALIZATION).create();
             if (useBinary) {
                 objects.add(serializer.serializeResponseAsBinary(error, ctx.alloc()));

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b29bab0a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
index 899d488..a1030cc 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
@@ -20,6 +20,7 @@ package org.apache.tinkerpop.gremlin.server.handler;
 
 import com.codahale.metrics.Meter;
 import com.codahale.metrics.Timer;
+import org.apache.commons.lang.exception.ExceptionUtils;
 import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
 import org.apache.tinkerpop.gremlin.driver.Tokens;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
@@ -49,7 +50,6 @@ import io.netty.handler.codec.http.HttpResponseStatus;
 import io.netty.handler.codec.http.QueryStringDecoder;
 import io.netty.util.CharsetUtil;
 import io.netty.util.ReferenceCountUtil;
-import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.tinkerpop.shaded.jackson.databind.JsonNode;
 import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
 import org.apache.tinkerpop.shaded.jackson.databind.node.ArrayNode;
@@ -457,8 +457,13 @@ public class HttpGremlinEndpointHandler extends ChannelInboundHandlerAdapter {
         errorMeter.mark();
         final ObjectNode node = mapper.createObjectNode();
         node.put("message", message);
-		if (t.isPresent()){
+		if (t.isPresent()) {
+            // "Exception-Class" needs to go away - didn't realize it was named that way during review for some reason.
+            // replaced with the same method for exception reporting as is used with websocket/nio protocol
 			node.put("Exception-Class", t.get().getClass().getName());
+            final ArrayNode exceptionList = node.putArray(Tokens.STATUS_ATTRIBUTE_EXCEPTIONS);
+            ExceptionUtils.getThrowableList(t.get()).forEach(throwable -> exceptionList.add(throwable.getClass().getName()));
+            node.put(Tokens.STATUS_ATTRIBUTE_STACK_TRACE, ExceptionUtils.getFullStackTrace(t.get()));
 		}
 		
         final FullHttpResponse response = new DefaultFullHttpResponse(

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b29bab0a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/IteratorHandler.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/IteratorHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/IteratorHandler.java
index 527aa37..78e2dc9 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/IteratorHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/IteratorHandler.java
@@ -110,7 +110,10 @@ public class IteratorHandler extends ChannelOutboundHandlerAdapter {
                     if (!f.isSuccess()) {
                         final String errorMessage = String.format("Response iteration and serialization exceeded the configured threshold for request [%s] - %s", msg, f.cause().getMessage());
                         logger.warn(errorMessage);
-                        ctx.writeAndFlush(ResponseMessage.build(requestMessage).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT).statusMessage(errorMessage).create());
+                        ctx.writeAndFlush(ResponseMessage.build(requestMessage)
+                                .code(ResponseStatusCode.SERVER_ERROR_TIMEOUT)
+                                .statusAttributeException(f.cause())
+                                .statusMessage(errorMessage).create());
                     }
                 });
             } finally {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b29bab0a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseEncoder.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseEncoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseEncoder.java
index 6a98b8b..79368c1 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseEncoder.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/NioGremlinResponseEncoder.java
@@ -25,6 +25,7 @@ import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
 import org.apache.tinkerpop.gremlin.server.GremlinServer;
+import org.apache.tinkerpop.gremlin.server.util.ExceptionHelper;
 import org.apache.tinkerpop.gremlin.server.util.MetricManager;
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandler;
@@ -72,10 +73,10 @@ public class NioGremlinResponseEncoder extends MessageToByteEncoder<ResponseMess
         } catch (Exception ex) {
             errorMeter.mark();
             logger.warn("The result [{}] in the request {} could not be serialized and returned.", responseMessage.getResult(), responseMessage.getRequestId(), ex);
-            final String errorMessage = String.format("Error during serialization: %s",
-                    ex.getCause() != null ? ex.getCause().getMessage() : ex.getMessage());
+            final String errorMessage = String.format("Error during serialization: %s", ExceptionHelper.getMessageFromExceptionOrCause(ex));
             final ResponseMessage error = ResponseMessage.build(responseMessage.getRequestId())
                     .statusMessage(errorMessage)
+                    .statusAttributeException(ex)
                     .code(ResponseStatusCode.SERVER_ERROR_SERIALIZATION).create();
             if (useBinary) {
                 final ByteBuf bytes = serializer.serializeResponseAsBinary(error, ctx.alloc());

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b29bab0a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpExecutorHandler.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpExecutorHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpExecutorHandler.java
index eefe600..477cb11 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpExecutorHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpExecutorHandler.java
@@ -77,6 +77,7 @@ public class OpExecutorHandler extends SimpleChannelInboundHandler<Pair<RequestM
             logger.warn(ex.getMessage(), ex);
             ctx.writeAndFlush(ResponseMessage.build(msg)
                     .code(ResponseStatusCode.SERVER_ERROR)
+                    .statusAttributeException(ex)
                     .statusMessage(ex.getMessage()).create());
         } finally {
             ReferenceCountUtil.release(objects);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b29bab0a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
index 432cecd..30055bf 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
@@ -90,7 +90,9 @@ public class OpSelectorHandler extends MessageToMessageDecoder<RequestMessage> {
             else {
                 // invalid op processor selected so write back an error by way of OpProcessorException.
                 final String errorMessage = String.format("Invalid OpProcessor requested [%s]", msg.getProcessor());
-                throw new OpProcessorException(errorMessage, ResponseMessage.build(msg).code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS).statusMessage(errorMessage).create());
+                throw new OpProcessorException(errorMessage, ResponseMessage.build(msg)
+                        .code(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS)
+                        .statusMessage(errorMessage).create());
             }
         } catch (OpProcessorException ope) {
             logger.warn(ope.getMessage(), ope);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b29bab0a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinResponseEncoder.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinResponseEncoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinResponseEncoder.java
index 80565f1..ecd5159 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinResponseEncoder.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsGremlinResponseEncoder.java
@@ -25,6 +25,7 @@ import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
 import org.apache.tinkerpop.gremlin.server.GremlinServer;
 import org.apache.tinkerpop.gremlin.server.op.session.Session;
+import org.apache.tinkerpop.gremlin.server.util.ExceptionHelper;
 import org.apache.tinkerpop.gremlin.server.util.MetricManager;
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandler;
@@ -89,10 +90,10 @@ public class WsGremlinResponseEncoder extends MessageToMessageEncoder<ResponseMe
         } catch (Exception ex) {
             errorMeter.mark();
             logger.warn("The result [{}] in the request {} could not be serialized and returned.", o.getResult(), o.getRequestId(), ex);
-            final String errorMessage = String.format("Error during serialization: %s",
-                    ex.getCause() != null ? ex.getCause().getMessage() : ex.getMessage());
+            final String errorMessage = String.format("Error during serialization: %s", ExceptionHelper.getMessageFromExceptionOrCause(ex));
             final ResponseMessage error = ResponseMessage.build(o.getRequestId())
                     .statusMessage(errorMessage)
+                    .statusAttributeException(ex)
                     .code(ResponseStatusCode.SERVER_ERROR_SERIALIZATION).create();
             if (useBinary) {
                 objects.add(new BinaryWebSocketFrame(serializer.serializeResponseAsBinary(error, ctx.alloc())));

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b29bab0a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
index 1ba6e36..ffbda08 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractEvalOpProcessor.java
@@ -254,20 +254,25 @@ public abstract class AbstractEvalOpProcessor extends AbstractOpProcessor {
                         // and by default disabled. we can remove this handling once we drop that setting all together
                         final String errorMessage = String.format("Response iteration exceeded the configured threshold for request [%s] - %s", msg, ex.getMessage());
                         logger.warn(errorMessage);
-                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT).statusMessage(errorMessage).create());
+                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT)
+                                .statusMessage(errorMessage)
+                                .statusAttributeException(ex).create());
                         if (managedTransactionsForRequest) attemptRollback(msg, context.getGraphManager(), settings.strictTransactionManagement);
                     } catch (InterruptedException ex) {
                         // interruption occurs if there is a forced timeout during result iteration. this timeout
                         // is driven by the script evaluation timeout so for consistency the message should be the same
                         final String errorMessage = String.format("Script evaluation exceeded the configured threshold for request [%s] - %s", msg, ex.getMessage());
                         logger.warn(errorMessage, ex);
-                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT).statusMessage(ex.getMessage()).create());
+                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT)
+                                .statusMessage(ex.getMessage())
+                                .statusAttributeException(ex).create());
                         if (managedTransactionsForRequest) attemptRollback(msg, context.getGraphManager(), settings.strictTransactionManagement);
                     } catch (Exception ex) {
                         logger.warn(String.format("Exception processing a script on request [%s].", msg), ex);
                         final String err = ex.getMessage();
                         ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR)
-                                .statusMessage(null == err || err.isEmpty() ? ex.getClass().getSimpleName() : err).create());
+                                .statusMessage(null == err || err.isEmpty() ? ex.getClass().getSimpleName() : err)
+                                .statusAttributeException(ex).create());
                         if (managedTransactionsForRequest) attemptRollback(msg, context.getGraphManager(), settings.strictTransactionManagement);
                     }
                 }).create();
@@ -284,16 +289,22 @@ public abstract class AbstractEvalOpProcessor extends AbstractOpProcessor {
                     // occurs when the TimedInterruptCustomizerProvider is in play
                     final String errorMessage = String.format("A timeout occurred within the script during evaluation of [%s] - consider increasing the limit given to TimedInterruptCustomizerProvider", msg);
                     logger.warn(errorMessage);
-                    ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT).statusMessage("Timeout during script evaluation triggered by TimedInterruptCustomizerProvider").create());
+                    ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT)
+                            .statusMessage("Timeout during script evaluation triggered by TimedInterruptCustomizerProvider")
+                            .statusAttributeException(t).create());
                 } else if (t instanceof org.apache.tinkerpop.gremlin.groovy.jsr223.TimedInterruptTimeoutException) {
                     // occurs when the TimedInterruptCustomizerProvider is in play
                     final String errorMessage = String.format("A timeout occurred within the script during evaluation of [%s] - consider increasing the limit given to TimedInterruptCustomizerProvider", msg);
                     logger.warn(errorMessage);
-                    ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT).statusMessage("Timeout during script evaluation triggered by TimedInterruptCustomizerProvider").create());
+                    ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT)
+                            .statusMessage("Timeout during script evaluation triggered by TimedInterruptCustomizerProvider")
+                            .statusAttributeException(t).create());
                 } else if (t instanceof TimeoutException) {
                     final String errorMessage = String.format("Script evaluation exceeded the configured threshold for request [%s] - %s", msg, t.getMessage());
                     logger.warn(errorMessage, t);
-                    ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT).statusMessage(t.getMessage()).create());
+                    ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT)
+                            .statusMessage(t.getMessage())
+                            .statusAttributeException(t).create());
                 } else {
                     // try to trap the specific jvm error of "Method code too large!" to re-write it as something nicer,
                     // but only re-write if it's the only error because otherwise we might lose some other important
@@ -305,10 +316,14 @@ public abstract class AbstractEvalOpProcessor extends AbstractOpProcessor {
                             ((MultipleCompilationErrorsException) t).getErrorCollector().getErrorCount() == 1) {
                         final String errorMessage = String.format("The Gremlin statement that was submitted exceed the maximum compilation size allowed by the JVM, please split it into multiple smaller statements - %s", msg);
                         logger.warn(errorMessage);
-                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION).statusMessage(errorMessage).create());
+                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION)
+                                .statusMessage(errorMessage)
+                                .statusAttributeException(t).create());
                     } else {
                         logger.warn(String.format("Exception processing a script on request [%s].", msg), t);
-                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION).statusMessage(t.getMessage()).create());
+                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION)
+                                .statusMessage(t.getMessage())
+                                .statusAttributeException(t).create());
                     }
                 }
             }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b29bab0a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractOpProcessor.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractOpProcessor.java
index c3ac475..8899bb5 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/AbstractOpProcessor.java
@@ -32,6 +32,7 @@ import org.apache.tinkerpop.gremlin.server.OpProcessor;
 import org.apache.tinkerpop.gremlin.server.Settings;
 import org.apache.tinkerpop.gremlin.server.handler.Frame;
 import org.apache.tinkerpop.gremlin.server.handler.StateKey;
+import org.apache.tinkerpop.gremlin.server.util.ExceptionHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -277,10 +278,10 @@ public abstract class AbstractOpProcessor implements OpProcessor {
             }
         } catch (Exception ex) {
             logger.warn("The result [{}] in the request {} could not be serialized and returned.", aggregate, msg.getRequestId(), ex);
-            final String errorMessage = String.format("Error during serialization: %s",
-                    ex.getCause() != null ? ex.getCause().getMessage() : ex.getMessage());
+            final String errorMessage = String.format("Error during serialization: %s", ExceptionHelper.getMessageFromExceptionOrCause(ex));
             final ResponseMessage error = ResponseMessage.build(msg.getRequestId())
                     .statusMessage(errorMessage)
+                    .statusAttributeException(ex)
                     .code(ResponseStatusCode.SERVER_ERROR_SERIALIZATION).create();
             ctx.writeAndFlush(error);
             throw ex;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b29bab0a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java
index c5a05e4..9d908ca 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java
@@ -299,12 +299,16 @@ public class TraversalOpProcessor extends AbstractOpProcessor {
                     } catch (TimeoutException ex) {
                         final String errorMessage = String.format("Response iteration exceeded the configured threshold for request [%s] - %s", msg.getRequestId(), ex.getMessage());
                         logger.warn(errorMessage);
-                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT).statusMessage(errorMessage).create());
+                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT)
+                                .statusMessage(errorMessage)
+                                .statusAttributeException(ex).create());
                         onError(graph, context);
                         return;
                     } catch (Exception ex) {
                         logger.warn(String.format("Exception processing a side-effect on iteration for request [%s].", msg.getRequestId()), ex);
-                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR).statusMessage(ex.getMessage()).create());
+                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR)
+                                .statusMessage(ex.getMessage())
+                                .statusAttributeException(ex).create());
                         onError(graph, context);
                         return;
                     }
@@ -312,7 +316,9 @@ public class TraversalOpProcessor extends AbstractOpProcessor {
                     onSideEffectSuccess(graph, context);
                 } catch (Exception ex) {
                     logger.warn(String.format("Exception processing a side-effect on request [%s].", msg.getRequestId()), ex);
-                    ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR).statusMessage(ex.getMessage()).create());
+                    ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR)
+                            .statusMessage(ex.getMessage())
+                            .statusAttributeException(ex).create());
                     onError(graph, context);
                 } finally {
                     timerContext.stop();
@@ -322,7 +328,9 @@ public class TraversalOpProcessor extends AbstractOpProcessor {
         } catch (Exception ex) {
             timerContext.stop();
             throw new OpProcessorException("Could not iterate the side-effect instance",
-                    ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR).statusMessage(ex.getMessage()).create());
+                    ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR)
+                            .statusMessage(ex.getMessage())
+                            .statusAttributeException(ex).create());
         }
     }
 
@@ -357,7 +365,8 @@ public class TraversalOpProcessor extends AbstractOpProcessor {
             logger.error("Could not deserialize the Traversal instance", context);
             throw new OpProcessorException("Could not deserialize the Traversal instance",
                     ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_SERIALIZATION)
-                            .statusMessage(ex.getMessage()).create());
+                            .statusMessage(ex.getMessage())
+                            .statusAttributeException(ex).create());
         }
 
         final Timer.Context timerContext = traversalOpTimer.time();
@@ -376,18 +385,24 @@ public class TraversalOpProcessor extends AbstractOpProcessor {
                     } catch (TimeoutException ex) {
                         final String errorMessage = String.format("Response iteration exceeded the configured threshold for request [%s] - %s", msg.getRequestId(), ex.getMessage());
                         logger.warn(errorMessage);
-                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT).statusMessage(errorMessage).create());
+                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR_TIMEOUT)
+                                .statusMessage(errorMessage)
+                                .statusAttributeException(ex).create());
                         onError(graph, context);
                         return;
                     } catch (Exception ex) {
                         logger.warn(String.format("Exception processing a Traversal on iteration for request [%s].", msg.getRequestId()), ex);
-                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR).statusMessage(ex.getMessage()).create());
+                        ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR)
+                                .statusMessage(ex.getMessage())
+                                .statusAttributeException(ex).create());
                         onError(graph, context);
                         return;
                     }
                 } catch (Exception ex) {
                     logger.warn(String.format("Exception processing a Traversal on request [%s].", msg.getRequestId()), ex);
-                    ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR).statusMessage(ex.getMessage()).create());
+                    ctx.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR)
+                            .statusMessage(ex.getMessage())
+                            .statusAttributeException(ex).create());
                     onError(graph, context);
                 } finally {
                     timerContext.stop();
@@ -397,7 +412,9 @@ public class TraversalOpProcessor extends AbstractOpProcessor {
         } catch (Exception ex) {
             timerContext.stop();
             throw new OpProcessorException("Could not iterate the Traversal instance",
-                    ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR).statusMessage(ex.getMessage()).create());
+                    ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR)
+                            .statusMessage(ex.getMessage())
+                            .statusAttributeException(ex).create());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b29bab0a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/ExceptionHelper.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/ExceptionHelper.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/ExceptionHelper.java
new file mode 100644
index 0000000..49eb8a6
--- /dev/null
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/ExceptionHelper.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * Utility class for working with exceptions.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public final class ExceptionHelper {
+
+    private ExceptionHelper() {}
+
+    public static String getMessageOrName(final Throwable t) {
+        return (null == t.getMessage() || t.getMessage().isEmpty()) ?
+            t.getClass().getName() : t.getMessage();
+    }
+
+    public static String getMessageFromExceptionOrCause(final Throwable t) {
+        return null == t.getCause() ? getMessageOrName(t) : getMessageOrName(t.getCause());
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b29bab0a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
index a8164b5..9eabf15 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
@@ -363,6 +363,11 @@ public class GremlinDriverIntegrateTest extends AbstractGremlinServerIntegration
             final Throwable inner = ExceptionUtils.getRootCause(ex);
             assertTrue(inner instanceof ResponseException);
             assertThat(inner.getMessage(), endsWith("Division by zero"));
+
+            final ResponseException rex = (ResponseException) inner;
+            assertEquals("java.lang.ArithmeticException", rex.getRemoteExceptionHierarchy().get().get(0));
+            assertEquals(1, rex.getRemoteExceptionHierarchy().get().size());
+            assertThat(rex.getRemoteStackTrace().get(), startsWith("java.lang.ArithmeticException: Division by zero\n\tat java.math.BigDecimal.divide(BigDecimal.java:1742)\n\tat org.codehaus.groovy.runtime.typehandling.BigDecimalMath.divideImpl(BigDecimalMath.java:68)\n\tat org.codehaus.groovy.runtime.typehandling.IntegerMath.divideImpl(IntegerMath.java:49)\n\tat org.codehaus.groovy.runtime.dgmimpl.NumberNumberDiv$NumberNumber.invoke(NumberNumberDiv.java:323)\n\tat org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)\n\tat org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)\n\tat org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)\n\tat org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)\n"));
         }
 
         // should not die completely just because we had a bad serialization error.  that kind of stuff happens

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b29bab0a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java
index 78109e6..b1cbd7f 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java
@@ -18,6 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.server;
 
+import org.apache.tinkerpop.gremlin.driver.Tokens;
 import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV2d0;
 import org.apache.tinkerpop.gremlin.server.auth.SimpleAuthenticator;
 import org.apache.tinkerpop.gremlin.server.channel.HttpChannelizer;
@@ -42,6 +43,8 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.StringStartsWith.startsWith;
 import static org.junit.Assert.assertEquals;
 
 /**
@@ -799,6 +802,11 @@ public class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra
 
         try (final CloseableHttpResponse response = httpclient.execute(httppost)) {
             assertEquals(500, response.getStatusLine().getStatusCode());
+            final String json = EntityUtils.toString(response.getEntity());
+            final JsonNode node = mapper.readTree(json);
+            assertEquals("java.lang.ArithmeticException", node.get(Tokens.STATUS_ATTRIBUTE_EXCEPTIONS).get(0).asText());
+            assertEquals(1, node.get(Tokens.STATUS_ATTRIBUTE_EXCEPTIONS).size());
+            assertThat(node.get(Tokens.STATUS_ATTRIBUTE_STACK_TRACE).asText(), startsWith("java.lang.ArithmeticException: Division by zero\n\tat java.math.BigDecimal.divide(BigDecimal.java:1742)\n\tat org.codehaus.groovy.runtime.typehandling.BigDecimalMath.divideImpl(BigDecimalMath.java:68)\n\tat org.codehaus.groovy.runtime.typehandling.IntegerMath.divideImpl(IntegerMath.java:49)\n\tat org.codehaus.groovy.runtime.dgmimpl.NumberNumberDiv$NumberNumber.invoke(NumberNumberDiv.java:323)\n\tat org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)\n\tat org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)\n\tat org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)\n\tat org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)\n"));
         }
     }