You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2015/08/04 16:25:46 UTC

[06/18] olingo-odata4 git commit: [OLINGO-731] Added html as debug output and refactored structure

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabBody.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabBody.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabBody.java
new file mode 100644
index 0000000..43e9ba6
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabBody.java
@@ -0,0 +1,149 @@
+/*
+ * 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.olingo.server.core.debug;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.regex.Pattern;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.olingo.commons.api.http.HttpHeader;
+import org.apache.olingo.server.api.ODataResponse;
+import org.apache.olingo.server.api.debug.DebugSupport;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+
+/**
+ * Response body debug information.
+ */
+public class DebugTabBody implements DebugTab {
+
+  private static enum ResponseContent {
+    JSON, XML, TEXT, IMAGE
+  };
+
+  private final ODataResponse response;
+  private final ResponseContent responseContent;
+
+  private final String serviceRoot;
+
+//  private final boolean isXml;
+//  private final boolean isJson;
+//  private final boolean isText;
+//  private final boolean isImage;
+
+  public DebugTabBody(final ODataResponse response, final String serviceRoot) {
+    this.response = response;
+    this.serviceRoot = serviceRoot;
+    final String contentType = response.getHeaders().get(HttpHeader.CONTENT_TYPE);
+    // TODO: Differentiate better
+    if (contentType != null) {
+      responseContent = ResponseContent.JSON;
+    } else {
+      responseContent = ResponseContent.TEXT;
+    }
+//    isXml = contentType.contains("xml");
+//    isJson = !isXml && contentType.startsWith(HttpContentType.APPLICATION_JSON);
+//    isText = isXml || isJson || contentType.startsWith("text/")
+//        || contentType.startsWith(HttpContentType.APPLICATION_HTTP)
+//        || contentType.startsWith(HttpContentType.MULTIPART_MIXED);
+//    isImage = !isText && contentType.startsWith("image/");
+  }
+
+  @Override
+  public String getName() {
+    return "Body";
+  }
+
+//
+  @Override
+  public void appendJson(final JsonGenerator gen) throws IOException {
+    if (response.getContent() == null) {
+      gen.writeNull();
+    } else {
+      gen.writeString(getContentString());
+    }
+  }
+
+  private String getContentString() {
+    try {
+      String contentString;
+      switch (responseContent) {
+      case IMAGE:
+        // TODO: DecodeString as base 64
+        contentString = "Currently not supported";
+        break;
+      case JSON:
+      case XML:
+      case TEXT:
+      default:
+        // TODO: Remove IOUtils from core dependency
+        contentString = IOUtils.toString(response.getContent(), "UTF-8");
+        break;
+      }
+      return contentString;
+    } catch (IOException e) {
+      return "Could not parse Body for Debug Output";
+    }
+  }
+
+  @Override
+  public void appendHtml(final Writer writer) throws IOException {
+
+    final String body = response.getContent() == null ? "ODataLibrary: null body." : getContentString();
+    switch (responseContent) {
+    case XML:
+      writer.append("<pre class=\"code").append("xml").append("\">\n");
+      writer.append(addLinks(DebugResponseHelperImpl.escapeHtml(body)));
+      writer.append("</pre>\n");
+      break;
+    case JSON:
+      writer.append("<pre class=\"code").append("json").append("\">\n");
+      writer.append(addLinks(DebugResponseHelperImpl.escapeHtml(body)));
+      writer.append("</pre>\n");
+      break;
+    case IMAGE:
+      // Make header query case insensitive
+      writer.append("<img src=\"data:").append(response.getHeaders().get(HttpHeader.CONTENT_TYPE)).append(";base64,")
+          .append(body)
+          .append("\" />\n");
+      break;
+    case TEXT:
+    default:
+      writer.append("<pre class=\"code").append("").append("\">\n");
+      writer.append(DebugResponseHelperImpl.escapeHtml(body));
+      writer.append("</pre>\n");
+      break;
+    }
+  }
+
+  private String addLinks(final String source) {
+    final String debugOption = DebugSupport.ODATA_DEBUG_QUERY_PARAMETER + "=" + DebugSupport.ODATA_DEBUG_HTML;
+    final String urlPattern = "("
+        + (responseContent == ResponseContent.XML ?
+            "(?:href|src|base)=" : "\"(?:uri|media_src|edit_media|__next)\":\\p{Space}*")
+        + "\")(.+?)\"";
+    return (responseContent == ResponseContent.XML ?
+        source.replaceAll("(xmlns(?::\\p{Alnum}+)?=\")(.+?)\"", "$1<span class=\"ns\">$2</span>\"") : source)
+        .replaceAll(urlPattern, "$1<a href=\"" + serviceRoot + "$2?" + debugOption + "\">$2</a>\"")
+        .replaceAll("(<a href=\"" + Pattern.quote(serviceRoot) + ')' + Pattern.quote(serviceRoot), "$1")
+        .replaceAll("<a href=\"(.+?)\\?(.+?)\\?" + debugOption, "<a href=\"$1?$2&amp;" + debugOption)
+        .replaceAll("&amp;amp;", "&amp;");
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabException.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabException.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabException.java
new file mode 100644
index 0000000..6bc69e4
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabException.java
@@ -0,0 +1,136 @@
+/*
+ * 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.olingo.server.core.debug;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.olingo.server.api.ODataLibraryException;
+import org.apache.olingo.server.api.ODataLibraryException.ODataErrorMessage;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+
+/**
+ * Exception debug information.
+ */
+public class DebugTabException implements DebugTab {
+
+  private final Exception exception;
+
+  public DebugTabException(final Exception exception) {
+    this.exception = exception;
+  }
+
+  @Override
+  public String getName() {
+    return "Stacktrace";
+  }
+
+  @Override
+  public void appendJson(final JsonGenerator gen) throws IOException {
+    gen.writeStartObject();
+    gen.writeFieldName("exceptions");
+    gen.writeStartArray();
+    Throwable throwable = exception;
+    while (throwable != null) {
+      gen.writeStartObject();
+      gen.writeStringField("class", throwable.getClass().getCanonicalName());
+      gen.writeStringField("message", getMessageText(throwable));
+      gen.writeFieldName("invocation");
+      appendJsonStackTraceElement(gen, throwable.getStackTrace()[0]);
+      gen.writeEndObject();
+
+      // Get next exception in the cause list
+      throwable = throwable.getCause();
+    }
+    gen.writeEndArray();
+
+    gen.writeFieldName("stacktrace");
+    gen.writeStartArray();
+    for (final StackTraceElement stackTraceElement : exception.getStackTrace()) {
+      appendJsonStackTraceElement(gen, stackTraceElement);
+    }
+    gen.writeEndArray();
+
+    gen.writeEndObject();
+  }
+
+  private String getMessageText(final Throwable throwable) {
+    String message;
+    if (throwable instanceof ODataLibraryException) {
+      ODataLibraryException ex = (ODataLibraryException) throwable;
+      // We use the default locale
+      ODataErrorMessage translatedMessage = ex.getTranslatedMessage(null);
+      // We provide the best message we can
+      message = translatedMessage.getMessage() == null ? ex.getMessage() : translatedMessage.getMessage();
+    } else {
+      message = throwable.getMessage();
+    }
+    return message;
+  }
+
+  private void appendJsonStackTraceElement(final JsonGenerator gen, final StackTraceElement element)
+      throws IOException {
+    gen.writeStartObject();
+    gen.writeStringField("class", element.getClassName());
+    gen.writeStringField("method", element.getMethodName());
+    gen.writeStringField("line", Integer.toString(element.getLineNumber()));
+    gen.writeEndObject();
+  }
+
+  @Override
+  public void appendHtml(final Writer writer) throws IOException {
+    appendException(exception, writer);
+    writer.append("<h2>Stacktrace</h2>\n");
+    int count = 0;
+    for (final StackTraceElement stackTraceElement : exception.getStackTrace()) {
+      appendStackTraceElement(stackTraceElement, ++count == 1, count == exception.getStackTrace().length, writer);
+    }
+  }
+
+  private void appendException(final Throwable throwable, final Writer writer) throws IOException {
+    if (throwable.getCause() != null) {
+      appendException(throwable.getCause(), writer);
+    }
+    final StackTraceElement details = throwable.getStackTrace()[0];
+    writer.append("<h2>").append(throwable.getClass().getCanonicalName()).append("</h2>\n")
+        .append("<p>")
+        .append(DebugResponseHelperImpl.escapeHtml(getMessageText(throwable)))
+        .append("</p>\n");
+    appendStackTraceElement(details, true, true, writer);
+  }
+
+  private void appendStackTraceElement(final StackTraceElement stackTraceElement,
+      final boolean isFirst, final boolean isLast, final Writer writer) throws IOException {
+    if (isFirst) {
+      writer.append("<table>\n<thead>\n")
+          .append("<tr>\n<th class=\"name\">Class</th>\n")
+          .append("<th class=\"name\">Method</th>\n")
+          .append("<th class=\"value\">Line number in class</th>\n</tr>\n")
+          .append("</thead>\n<tbody>\n");
+    }
+    writer.append("<tr>\n<td class=\"name\">").append(stackTraceElement.getClassName()).append("</td>\n")
+        .append("<td class=\"name\">").append(stackTraceElement.getMethodName()).append("</td>\n")
+        .append("<td class=\"value\">").append(Integer.toString(stackTraceElement.getLineNumber()))
+        .append("</td>\n</tr>\n");
+    if (isLast) {
+      writer.append("</tbody>\n</table>\n");
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabRequest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabRequest.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabRequest.java
new file mode 100644
index 0000000..8eba537
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabRequest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.olingo.server.core.debug;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.server.api.ODataRequest;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+
+/**
+ * Request debug information.
+ */
+public class DebugTabRequest implements DebugTab {
+
+  private final String method;
+  private final String uri;
+  private final String protocol;
+  private final Map<String, String> headers;
+
+  public DebugTabRequest(ODataRequest request) {
+    method = request.getMethod() == null ? "unkown" : request.getMethod().toString();
+    uri = request.getRawRequestUri() == null ? "unkown" : request.getRawRequestUri();
+    protocol = request.getProtocol() == null ? "unkown" : request.getProtocol();
+    // TODO: Should we really wrap the headers here or keep the original structure?
+    headers = wrapHeaders(request.getAllHeaders());
+  }
+
+  private Map<String, String> wrapHeaders(Map<String, List<String>> allHeaders) {
+    Map<String, String> localHeaders = new LinkedHashMap<String, String>();
+    for (Map.Entry<String, List<String>> entry : allHeaders.entrySet()) {
+      String value = null;
+      if (entry.getValue() != null) {
+        value = "";
+        boolean first = true;
+        for (String valuePart : entry.getValue()) {
+          if (!first) {
+            value = value + ", ";
+          }
+          value = value + valuePart;
+        }
+      }
+      localHeaders.put(entry.getKey(), value);
+    }
+    return localHeaders;
+  }
+
+  @Override
+  public void appendHtml(final Writer writer) throws IOException {
+    writer.append("<h2>Request Method</h2>\n")
+        .append("<p>").append(method).append("</p>\n")
+        .append("<h2>Request URI</h2>\n")
+        .append("<p>").append(DebugResponseHelperImpl.escapeHtml(uri.toString())).append("</p>\n")
+        .append("<h2>Request Protocol</h2>\n")
+        .append("<p>").append(protocol).append("</p>\n");
+    writer.append("<h2>Request Headers</h2>\n");
+    DebugResponseHelperImpl.appendHtmlTable(writer, headers);
+
+//        .append("<table>\n<thead>\n")
+//        .append("<tr><th class=\"name\">Name</th><th class=\"value\">Value</th></tr>\n")
+//        .append("</thead>\n<tbody>\n");
+//    for (final String name : headers.keySet()) {
+//      for (final String value : headers.get(name)) {
+//        if (value != null) {
+//          writer.append("<tr><td class=\"name\">").append(name).append("</td>")
+//              .append("<td class=\"value\">").append(DebugResponseHelperImpl.escapeHtml(value))
+//              .append("</td></tr>\n");
+//        }
+//      }
+//    }
+//    writer.append("</tbody>\n</table>\n");
+  }
+
+  @Override
+  public String getName() {
+    return "Request";
+  }
+
+  @Override
+  public void appendJson(JsonGenerator gen) throws IOException {
+    gen.writeStartObject();
+    gen.writeStringField("method", method);
+
+    gen.writeStringField("uri", uri);
+
+    gen.writeStringField("protocol", protocol);
+
+    if (!headers.isEmpty()) {
+      gen.writeFieldName("headers");
+      DebugResponseHelperImpl.appendJsonTable(gen, headers);
+    }
+
+    gen.writeEndObject();
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabResponse.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabResponse.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabResponse.java
new file mode 100644
index 0000000..5cb153c
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabResponse.java
@@ -0,0 +1,89 @@
+/*
+ * 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.olingo.server.core.debug;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Map;
+
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.server.api.ODataResponse;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+
+/**
+ * Response debug information.
+ */
+public class DebugTabResponse implements DebugTab {
+
+  private final ODataResponse response;
+  private final String serviceRoot;
+  private final HttpStatusCode status;
+  private final Map<String, String> headers;
+
+  public DebugTabResponse(final ODataResponse applicationResponse, final String serviceRoot) {
+    this.response = applicationResponse;
+    this.serviceRoot = serviceRoot;
+    status = HttpStatusCode.fromStatusCode(response.getStatusCode());
+    headers = response.getHeaders();
+  }
+
+  @Override
+  public String getName() {
+    return "Response";
+  }
+
+  @Override
+  public void appendJson(final JsonGenerator gen) throws IOException {
+    gen.writeStartObject();
+
+    if (status != null) {
+      gen.writeFieldName("status");
+      gen.writeStartObject();
+      gen.writeStringField("code", Integer.toString(status.getStatusCode()));
+      gen.writeStringField("info", status.getInfo());
+      gen.writeEndObject();
+    }
+
+    if (headers != null && !headers.isEmpty()) {
+      gen.writeFieldName("headers");
+      DebugResponseHelperImpl.appendJsonTable(gen, headers);
+    }
+
+    gen.writeFieldName("body");
+    new DebugTabBody(response, serviceRoot).appendJson(gen);
+
+    gen.writeEndObject();
+  }
+
+  @Override
+  public void appendHtml(final Writer writer) throws IOException {
+    writer.append("<h2>Status Code</h2>\n")
+        .append("<p>").append(Integer.toString(status.getStatusCode())).append(' ')
+        .append(status.getInfo()).append("</p>\n")
+        .append("<h2>Response Headers</h2>\n");
+    DebugResponseHelperImpl.appendHtmlTable(writer, headers);
+    writer.append("<h2>Response Body</h2>\n");
+    if (response.getContent() != null) {
+      new DebugTabBody(response, serviceRoot).appendHtml(writer);
+    } else {
+      writer.append("<p>ODataLibrary: no response body</p>");
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabRuntime.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabRuntime.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabRuntime.java
new file mode 100644
index 0000000..312b4cd
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabRuntime.java
@@ -0,0 +1,181 @@
+/*
+ * 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.olingo.server.core.debug;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.olingo.server.api.debug.RuntimeMeasurement;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+
+/**
+ * Runtime debug information.
+ */
+public class DebugTabRuntime implements DebugTab {
+
+  private final RuntimeNode rootNode;
+
+  public DebugTabRuntime(List<RuntimeMeasurement> runtimeInformation) {
+    rootNode = new RuntimeNode();
+    for (final RuntimeMeasurement runtimeMeasurement : runtimeInformation) {
+      rootNode.add(runtimeMeasurement);
+    }
+    rootNode.combineRuntimeMeasurements();
+  }
+
+  @Override
+  public String getName() {
+    return "Runtime";
+  }
+
+  @Override
+  public void appendJson(JsonGenerator gen) throws IOException {
+    appendJsonChildren(gen, rootNode);
+  }
+
+  private void appendJsonChildren(JsonGenerator gen, RuntimeNode node) throws IOException {
+    gen.writeStartArray();
+    for (RuntimeNode child : node.children) {
+      appendJsonNode(gen, child);
+    }
+    gen.writeEndArray();
+  }
+
+  private void appendJsonNode(JsonGenerator gen, RuntimeNode node) throws IOException {
+    gen.writeStartObject();
+    gen.writeStringField("class", node.className);
+    gen.writeStringField("method ", node.methodName);
+
+    if (node.timeStopped == 0) {
+      gen.writeNullField("duration");
+    } else {
+      gen.writeStringField("duration", Long.toString((node.timeStopped - node.timeStarted) / 1000));
+      gen.writeStringField("unit", "µs");
+    }
+
+    if (!node.children.isEmpty()) {
+      gen.writeFieldName("children");
+      appendJsonChildren(gen, node);
+    }
+
+    gen.writeEndObject();
+  }
+
+  @Override
+  public void appendHtml(final Writer writer) throws IOException {
+    appendRuntimeNode(rootNode, "", true, writer);
+  }
+
+  private void appendRuntimeNode(final RuntimeNode node, final String draw, final boolean isLast, final Writer writer)
+      throws IOException {
+    if (node.className != null) {
+      writer.append("<li>")
+          .append("<span class=\"code\">")
+          .append("<span class=\"draw\">").append(draw)
+          .append(isLast ? "&#x2514;" : "&#x251C;").append("&#x2500;&nbsp;</span>")
+          .append("<span class=\"class\">").append(node.className).append("</span>.")
+          .append("<span class=\"method\">").append(node.methodName).append("(&hellip;)")
+          .append("</span></span>");
+      long time = node.timeStopped == 0 ? 0 : (node.timeStopped - node.timeStarted) / 1000;
+      writer.append("<span class=\"").append(time == 0 ? "null" : "numeric")
+          .append("\" title=\"").append(time == 0 ? "Stop time missing" : "Gross duration")
+          .append("\">").append(time == 0 ? "unfinished" : Long.toString(time) + "&nbsp;&micro;s")
+          .append("</span>\n");
+    }
+    if (!node.children.isEmpty()) {
+      writer.append("<ol class=\"tree\">\n");
+      for (final RuntimeNode childNode : node.children) {
+        appendRuntimeNode(childNode,
+            node.className == null ? draw : draw + (isLast ? "&nbsp;" : "&#x2502;") + "&nbsp;&nbsp;",
+            node.children.indexOf(childNode) == node.children.size() - 1,
+            writer);
+      }
+      writer.append("</ol>\n");
+    }
+    if (node.className != null) {
+      writer.append("</li>\n");
+    }
+  }
+
+  private class RuntimeNode {
+
+    protected String className;
+    protected String methodName;
+    protected long timeStarted;
+    protected long timeStopped;
+    protected List<RuntimeNode> children = new ArrayList<RuntimeNode>();
+
+    protected RuntimeNode() {
+      timeStarted = 0;
+      timeStopped = Long.MAX_VALUE;
+    }
+
+    private RuntimeNode(final RuntimeMeasurement runtimeMeasurement) {
+      className = runtimeMeasurement.getClassName();
+      methodName = runtimeMeasurement.getMethodName();
+      timeStarted = runtimeMeasurement.getTimeStarted();
+      timeStopped = runtimeMeasurement.getTimeStopped();
+    }
+
+    protected boolean add(final RuntimeMeasurement runtimeMeasurement) {
+      if (timeStarted <= runtimeMeasurement.getTimeStarted()
+          && timeStopped != 0 && timeStopped >= runtimeMeasurement.getTimeStopped()) {
+        for (RuntimeNode candidate : children) {
+          if (candidate.add(runtimeMeasurement)) {
+            return true;
+          }
+        }
+        children.add(new RuntimeNode(runtimeMeasurement));
+        return true;
+      } else {
+        return false;
+      }
+    }
+
+    /**
+     * Combines runtime measurements with identical class names and method
+     * names into one measurement, assuming that they originate from a loop
+     * or a similar construct where a summary measurement has been intended.
+     */
+    protected void combineRuntimeMeasurements() {
+      RuntimeNode preceding = null;
+      for (Iterator<RuntimeNode> iterator = children.iterator(); iterator.hasNext();) {
+        final RuntimeNode child = iterator.next();
+        if (preceding != null
+            && preceding.timeStopped != 0 && child.timeStopped != 0
+            && preceding.timeStopped <= child.timeStarted
+            && preceding.children.isEmpty() && child.children.isEmpty()
+            && preceding.methodName.equals(child.methodName)
+            && preceding.className.equals(child.className)) {
+          preceding.timeStarted = child.timeStarted - (preceding.timeStopped - preceding.timeStarted);
+          preceding.timeStopped = child.timeStopped;
+
+          iterator.remove();
+        } else {
+          preceding = child;
+          child.combineRuntimeMeasurements();
+        }
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabServer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabServer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabServer.java
new file mode 100644
index 0000000..4eb95ba
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabServer.java
@@ -0,0 +1,57 @@
+/*
+ * 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.olingo.server.core.debug;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Map;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+
+/**
+ * Server debug information.
+ */
+public class DebugTabServer implements DebugTab {
+
+  private final Map<String, String> serverEnvironmentVaribles;
+
+  public DebugTabServer(Map<String, String> serverEnvironmentVaribles) {
+    this.serverEnvironmentVaribles = serverEnvironmentVaribles;
+  }
+
+  @Override
+  public String getName() {
+    return "Environment";
+  }
+
+  @Override
+  public void appendJson(JsonGenerator gen) throws IOException {
+    DebugResponseHelperImpl.appendJsonTable(gen, serverEnvironmentVaribles);
+  }
+
+  @Override
+  public void appendHtml(Writer writer) throws IOException {
+    final Package pack = DebugResponseHelperImpl.class.getPackage();
+    writer.append("<h2>Library Version</h2>\n")
+        .append("<p>").append(pack.getImplementationTitle())
+        .append(" Version ").append(pack.getImplementationVersion()).append("</p>\n")
+        .append("<h2>Server Environment</h2>\n");
+    DebugResponseHelperImpl.appendHtmlTable(writer, serverEnvironmentVaribles);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabUri.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabUri.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabUri.java
new file mode 100644
index 0000000..5c50c0f
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/DebugTabUri.java
@@ -0,0 +1,232 @@
+/*
+ * 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.olingo.server.core.debug;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.olingo.server.api.uri.UriInfo;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+
+
+/**
+ * URI parser debug information.
+ */
+public class DebugTabUri implements DebugTab {
+
+  private UriInfo uriInfo;
+
+  public DebugTabUri(UriInfo uriInfo) {
+    this.uriInfo = uriInfo;
+  }
+
+  @Override
+  public String getName() {
+    return "URI";
+  }
+
+  @Override
+  public void appendJson(JsonGenerator jsonGenerator) throws IOException {
+    // TODO Auto-generated method stub
+    
+  }
+
+  @Override
+  public void appendHtml(Writer writer) throws IOException {
+    // TODO Auto-generated method stub
+    
+  }
+
+//  private final UriInfo uriInfo;
+//  private final FilterExpression filter;
+//  private final OrderByExpression orderBy;
+//  private final ExpandSelectTreeNodeImpl expandSelectTree;
+//  private final ExpressionParserException exception;
+//
+//  public DebugInfoUri(final UriInfo uriInfo, final ExpressionParserException exception) {
+//    this.uriInfo = uriInfo;
+//    filter = uriInfo == null ? null : uriInfo.getFilter();
+//    orderBy = uriInfo == null ? null : uriInfo.getOrderBy();
+//    expandSelectTree = uriInfo == null ? null : getExpandSelect();
+//    this.exception = exception;
+//  }
+//
+//  private ExpandSelectTreeNodeImpl getExpandSelect() {
+//    try {
+//      return uriInfo.getExpand().isEmpty() && uriInfo.getSelect().isEmpty() ? null :
+//          new ExpandSelectTreeCreator(uriInfo.getSelect(), uriInfo.getExpand()).create();
+//    } catch (final EdmException e) {
+//      return null;
+//    }
+//  }
+//  @Override
+//  public void appendJson(final JsonStreamWriter jsonStreamWriter) throws IOException {
+//    jsonStreamWriter.beginObject();
+//
+//    if (exception != null && exception.getFilterTree() != null) {
+//      jsonStreamWriter.name("error")
+//          .beginObject()
+//          .namedStringValue("expression", exception.getFilterTree().getUriLiteral())
+//          .endObject();
+//      if (filter != null || orderBy != null || expandSelectTree != null) {
+//        jsonStreamWriter.separator();
+//      }
+//    }
+//
+//    if (filter != null) {
+//      String filterString;
+//      try {
+//        filterString = (String) filter.accept(new JsonVisitor());
+//      } catch (final ExceptionVisitExpression e) {
+//        filterString = null;
+//      } catch (final ODataApplicationException e) {
+//        filterString = null;
+//      }
+//      jsonStreamWriter.name("filter").unquotedValue(filterString);
+//      if (orderBy != null || expandSelectTree != null) {
+//        jsonStreamWriter.separator();
+//      }
+//    }
+//
+//    if (orderBy != null) {
+//      String orderByString;
+//      try {
+//        orderByString = (String) orderBy.accept(new JsonVisitor());
+//      } catch (final ExceptionVisitExpression e) {
+//        orderByString = null;
+//      } catch (final ODataApplicationException e) {
+//        orderByString = null;
+//      }
+//      jsonStreamWriter.name("orderby").unquotedValue(orderByString);
+//      if (expandSelectTree != null) {
+//        jsonStreamWriter.separator();
+//      }
+//    }
+//
+//    if (expandSelectTree != null) {
+//      jsonStreamWriter.name("expandSelect").unquotedValue(expandSelectTree.toJsonString());
+//    }
+//
+//    jsonStreamWriter.endObject();
+//  }
+//
+//  @Override
+//  public void appendHtml(final Writer writer) throws IOException {
+//    if (exception != null && exception.getFilterTree() != null) {
+//      writer.append("<h2>Expression Information</h2>\n")
+//          .append("<pre class=\"code\">").append(exception.getFilterTree().getUriLiteral())
+//          .append("</pre>\n");
+//      // TODO: filter error position, filter tokens, filter tree
+//    }
+//    if (filter != null) {
+//      writer.append("<h2>Filter</h2>\n")
+//          .append("<ul class=\"expr\"><li>");
+//      appendExpression(filter.getExpression(), writer);
+//      writer.append("</li></ul>\n");
+//    }
+//    if (orderBy != null) {
+//      writer.append("<h2>Orderby</h2>\n")
+//          .append(orderBy.getOrdersCount() == 1 ? "<ul" : "<ol").append(" class=\"expr\">\n");
+//      for (final OrderExpression order : orderBy.getOrders()) {
+//        writer.append("<li>");
+//        appendExpression(order.getExpression(), writer);
+//        final ExpressionKind kind = order.getExpression().getKind();
+//        if (kind == ExpressionKind.PROPERTY || kind == ExpressionKind.LITERAL) {
+//          writer.append("<br />");
+//        }
+//        writer.append("<span class=\"order\">")
+//            .append(order.getSortOrder().toString())
+//            .append("</span></li>\n");
+//      }
+//      writer.append(orderBy.getOrdersCount() == 1 ? "</ul" : "</ol").append(">\n");
+//    }
+//    if (expandSelectTree != null) {
+//      writer.append("<h2>Expand/Select</h2>\n");
+//      appendExpandSelect(expandSelectTree, writer);
+//    }
+//  }
+//
+//  private void appendExpression(final CommonExpression expression, final Writer writer) throws IOException {
+//    final ExpressionKind kind = expression.getKind();
+//    writer.append("<span class=\"kind\">")
+//        .append(kind.toString())
+//        .append("</span> <span class=\"literal\">")
+//        .append(kind == ExpressionKind.MEMBER ? ((MemberExpression) expression).getProperty().getUriLiteral() :
+//            expression.getUriLiteral())
+//        .append("</span>, type <span class=\"type\">")
+//        .append(expression.getEdmType().toString())
+//        .append("</span>");
+//    if (kind == ExpressionKind.UNARY) {
+//      writer.append("<ul class=\"expr\"><li>");
+//      appendExpression(((UnaryExpression) expression).getOperand(), writer);
+//      writer.append("</li></ul>");
+//    } else if (kind == ExpressionKind.BINARY) {
+//      writer.append("<ol class=\"expr\"><li>");
+//      appendExpression(((BinaryExpression) expression).getLeftOperand(), writer);
+//      writer.append("</li><li>");
+//      appendExpression(((BinaryExpression) expression).getRightOperand(), writer);
+//      writer.append("</li></ol>");
+//    } else if (kind == ExpressionKind.METHOD) {
+//      final MethodExpression methodExpression = (MethodExpression) expression;
+//      if (methodExpression.getParameterCount() > 0) {
+//        writer.append("<ol class=\"expr\">");
+//        for (final CommonExpression parameter : methodExpression.getParameters()) {
+//          writer.append("<li>");
+//          appendExpression(parameter, writer);
+//          writer.append("</li>");
+//        }
+//        writer.append("</ol>");
+//      }
+//    } else if (kind == ExpressionKind.MEMBER) {
+//      writer.append("<ul class=\"expr\"><li>");
+//      appendExpression(((MemberExpression) expression).getPath(), writer);
+//      writer.append("</li></ul>");
+//    }
+//  }
+//
+//  private void appendExpandSelect(final ExpandSelectTreeNode expandSelect, final Writer writer) throws IOException {
+//    writer.append("<ul class=\"expand\">\n")
+//        .append("<li>");
+//    if (expandSelect.isAll()) {
+//      writer.append("all properties");
+//    } else {
+//      for (final EdmProperty property : expandSelect.getProperties()) {
+//        try {
+//          writer.append("property <span class=\"prop\">")
+//              .append(property.getName())
+//              .append("</span><br />");
+//        } catch (final EdmException e) {}
+//      }
+//    }
+//    writer.append("</li>\n");
+//    if (!expandSelect.getLinks().isEmpty()) {
+//      for (final String name : expandSelect.getLinks().keySet()) {
+//        writer.append("<li>link <span class=\"link\">").append(name).append("</span>");
+//        final ExpandSelectTreeNode link = expandSelect.getLinks().get(name);
+//        if (link != null) {
+//          writer.append('\n');
+//          appendExpandSelect(link, writer);
+//        }
+//        writer.append("</li>\n");
+//      }
+//    }
+//    writer.append("</ul>\n");
+//  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/ServerCoreDebugger.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/ServerCoreDebugger.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/ServerCoreDebugger.java
new file mode 100644
index 0000000..fcf611d
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/debug/ServerCoreDebugger.java
@@ -0,0 +1,137 @@
+/*
+ * 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.olingo.server.core.debug;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.api.http.HttpHeader;
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.ODataRequest;
+import org.apache.olingo.server.api.ODataResponse;
+import org.apache.olingo.server.api.debug.DebugInformation;
+import org.apache.olingo.server.api.debug.DebugSupport;
+import org.apache.olingo.server.api.debug.RuntimeMeasurement;
+import org.apache.olingo.server.api.uri.UriInfo;
+
+public class ServerCoreDebugger {
+
+  private final List<RuntimeMeasurement> runtimeInformation = new ArrayList<RuntimeMeasurement>();
+  private final OData odata;
+
+  private boolean isDebugMode = false;
+  private DebugSupport debugSupport;
+  private String debugFormat;
+
+  public ServerCoreDebugger(OData odata) {
+    this.odata = odata;
+  }
+
+  public void resolveDebugMode(HttpServletRequest request) {
+    if (debugSupport != null) {
+      // Should we read the parameter from the servlet here and ignore multiple parameters?
+      debugFormat = request.getParameter(DebugSupport.ODATA_DEBUG_QUERY_PARAMETER);
+      if (debugFormat != null) {
+        debugSupport.init(odata);
+        isDebugMode = debugSupport.isUserAuthorized();
+      }
+    }
+  }
+
+  public ODataResponse createDebugResponse(final HttpServletRequest request, final Exception exception,
+      final ODataRequest odRequest, final ODataResponse odResponse, UriInfo uriInfo,
+      Map<String, String> serverEnvironmentVaribles) {
+    try {
+      DebugInformation debugInfo =
+          createDebugInformation(request, exception, odRequest, odResponse, uriInfo, serverEnvironmentVaribles);
+
+      return debugSupport.createDebugResponse(debugFormat, debugInfo);
+    } catch (Exception e) {
+      return createFailResponse();
+    }
+  }
+
+  private ODataResponse createFailResponse() {
+    ODataResponse odResponse = new ODataResponse();
+    odResponse.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode());
+    odResponse.setHeader(HttpHeader.CONTENT_TYPE, ContentType.TEXT_PLAIN.toContentTypeString());
+    InputStream content = new ByteArrayInputStream("ODataLibrary: Could not assemble debug response.".getBytes());
+    odResponse.setContent(content);
+    return null;
+  }
+
+  private DebugInformation createDebugInformation(final HttpServletRequest request, final Exception exception,
+      final ODataRequest odRequest, final ODataResponse odResponse, UriInfo uriInfo,
+      Map<String, String> serverEnvironmentVaribles) {
+    DebugInformation debugInfo = new DebugInformation();
+    debugInfo.setRequest(odRequest);
+    debugInfo.setApplicationResponse(odResponse);
+
+    debugInfo.setException(exception);
+
+    debugInfo.setServerEnvironmentVaribles(serverEnvironmentVaribles);
+
+    debugInfo.setUriInfo(uriInfo);
+
+    debugInfo.setRuntimeInformation(runtimeInformation);
+    return debugInfo;
+  }
+
+  public int startRuntimeMeasurement(final String className, final String methodName) {
+    if (isDebugMode) {
+      int handleId = runtimeInformation.size();
+
+      final RuntimeMeasurement measurement = new RuntimeMeasurement();
+      measurement.setTimeStarted(System.nanoTime());
+      measurement.setClassName(className);
+      measurement.setMethodName(methodName);
+
+      runtimeInformation.add(measurement);
+
+      return handleId;
+    } else {
+      return 0;
+    }
+  }
+
+  public void stopRuntimeMeasurement(final int handle) {
+    if (isDebugMode && handle < runtimeInformation.size()) {
+      long stopTime = System.nanoTime();
+      RuntimeMeasurement runtimeMeasurement = runtimeInformation.get(handle);
+      if (runtimeMeasurement != null) {
+        runtimeMeasurement.setTimeStopped(stopTime);
+      }
+    }
+  }
+
+  public void setDebugSupportProcessor(DebugSupport debugSupport) {
+    this.debugSupport = debugSupport;
+  }
+
+  public boolean isDebugMode() {
+    return isDebugMode;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java
index 0b5922c..8b74a88 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java
@@ -36,7 +36,6 @@ import org.apache.olingo.server.api.ServiceMetadata;
 import org.apache.olingo.server.api.debug.DefaultDebugSupport;
 import org.apache.olingo.server.api.edmx.EdmxReference;
 import org.apache.olingo.server.api.edmx.EdmxReferenceInclude;
-import org.apache.olingo.server.tecsvc.async.TechnicalAsyncService;
 import org.apache.olingo.server.tecsvc.data.DataProvider;
 import org.apache.olingo.server.tecsvc.processor.TechnicalActionProcessor;
 import org.apache.olingo.server.tecsvc.processor.TechnicalBatchProcessor;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/3dae763f/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
index 236c1b7..5b347d1 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
@@ -6,9 +6,9 @@
  * 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
@@ -77,6 +77,7 @@ import org.apache.olingo.server.api.processor.ReferenceCollectionProcessor;
 import org.apache.olingo.server.api.processor.ReferenceProcessor;
 import org.apache.olingo.server.api.processor.ServiceDocumentProcessor;
 import org.apache.olingo.server.api.uri.UriInfo;
+import org.apache.olingo.server.core.debug.ServerCoreDebugger;
 import org.apache.olingo.server.tecsvc.provider.ContainerProvider;
 import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
 import org.junit.Test;
@@ -233,7 +234,8 @@ public class ODataHandlerTest {
     request.setMethod(HttpMethod.GET);
     request.setRawODataPath("EdmException");
 
-    final ODataResponse response = new ODataHandler(odata, serviceMetadata).process(request);
+    final ODataResponse response =
+        new ODataHandler(odata, serviceMetadata, new ServerCoreDebugger(odata)).process(request);
     assertNotNull(response);
     assertEquals(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatusCode());
   }
@@ -720,7 +722,7 @@ public class ODataHandlerTest {
     final ServiceMetadata metadata = odata.createServiceMetadata(
         new EdmTechProvider(), Collections.<EdmxReference> emptyList());
 
-    ODataHandler handler = new ODataHandler(odata, metadata);
+    ODataHandler handler = new ODataHandler(odata, metadata, new ServerCoreDebugger(odata));
 
     if (processor != null) {
       handler.register(processor);