From ece545ba084eff8772b1b9662b44c4e794b2a195 Mon Sep 17 00:00:00 2001 From: Crim Date: Wed, 2 Jan 2019 11:07:55 +0900 Subject: [PATCH] [ISSUE-114] Better expose underlying errors --- CHANGELOG.md | 1 + .../ui/controller/api/ApiController.java | 2 +- .../ui/manager/kafka/dto/ApiErrorCause.java | 83 +++++++++++++++++++ .../manager/kafka/dto/ApiErrorResponse.java | 51 +++++++++++- 4 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 kafka-webview-ui/src/main/java/org/sourcelab/kafka/webview/ui/manager/kafka/dto/ApiErrorCause.java diff --git a/CHANGELOG.md b/CHANGELOG.md index d7933002..47d1cbd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## 2.1.1 (UNRELEASED) #### New Features - Added ability to Copy previously created views. +- Better expose underlying exceptions/errors when things go wrong. #### Bug fixes - [ISSUE-116](https://github.com/SourceLabOrg/kafka-webview/issues/116) No longer require KeyStore and KeyStore password when configuring a SSL+SASL cluster. diff --git a/kafka-webview-ui/src/main/java/org/sourcelab/kafka/webview/ui/controller/api/ApiController.java b/kafka-webview-ui/src/main/java/org/sourcelab/kafka/webview/ui/controller/api/ApiController.java index b00ff1e3..fbe11ac7 100644 --- a/kafka-webview-ui/src/main/java/org/sourcelab/kafka/webview/ui/controller/api/ApiController.java +++ b/kafka-webview-ui/src/main/java/org/sourcelab/kafka/webview/ui/controller/api/ApiController.java @@ -570,7 +570,7 @@ public boolean removeConsumer( @ExceptionHandler(ApiException.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ApiErrorResponse handleApiException(final ApiException exception) { - return new ApiErrorResponse(exception.getType(), exception.getMessage()); + return new ApiErrorResponse(exception.getType(), exception.getMessage(), ApiErrorResponse.buildCauseList(exception)); } /** diff --git a/kafka-webview-ui/src/main/java/org/sourcelab/kafka/webview/ui/manager/kafka/dto/ApiErrorCause.java b/kafka-webview-ui/src/main/java/org/sourcelab/kafka/webview/ui/manager/kafka/dto/ApiErrorCause.java new file mode 100644 index 00000000..d1f0c02b --- /dev/null +++ b/kafka-webview-ui/src/main/java/org/sourcelab/kafka/webview/ui/manager/kafka/dto/ApiErrorCause.java @@ -0,0 +1,83 @@ +/** + * MIT License + * + * Copyright (c) 2017, 2018 SourceLab.org (https://github.com/Crim/kafka-webview/) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.sourcelab.kafka.webview.ui.manager.kafka.dto; + +/** + * Underlying causes for Api Error. + */ +public class ApiErrorCause { + private final String type; + private final String message; + private final String file; + private final String method; + private final int line; + + /** + * Constructor. + * @param type Classname of exception. + * @param message Error msg. + * @param file File the exception was generated from. + * @param method Method the exception was generated from. + * @param line line number the exception was generated from. + */ + public ApiErrorCause(final String type, final String message, final String file, final String method, final int line) { + this.type = type; + this.message = message; + this.file = file; + this.method = method; + this.line = line; + } + + public String getType() { + return type; + } + + public String getMessage() { + return message; + } + + public String getFile() { + return file; + } + + public String getMethod() { + return method; + } + + public int getLine() { + return line; + } + + @Override + public String toString() { + return "ApiErrorCause{" + + "type='" + type + '\'' + + ", message='" + message + '\'' + + ", file='" + file + '\'' + + ", method='" + method + '\'' + + ", line=" + line + + '}'; + } +} diff --git a/kafka-webview-ui/src/main/java/org/sourcelab/kafka/webview/ui/manager/kafka/dto/ApiErrorResponse.java b/kafka-webview-ui/src/main/java/org/sourcelab/kafka/webview/ui/manager/kafka/dto/ApiErrorResponse.java index fc9e6a33..26796d95 100644 --- a/kafka-webview-ui/src/main/java/org/sourcelab/kafka/webview/ui/manager/kafka/dto/ApiErrorResponse.java +++ b/kafka-webview-ui/src/main/java/org/sourcelab/kafka/webview/ui/manager/kafka/dto/ApiErrorResponse.java @@ -24,6 +24,10 @@ package org.sourcelab.kafka.webview.ui.manager.kafka.dto; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** * Represents an error returned over the API. */ @@ -31,13 +35,15 @@ public class ApiErrorResponse { private final boolean error = true; private final String message; private final String requestType; + private final ApiErrorCause[] causes; /** * Constructor. */ - public ApiErrorResponse(final String requestType, final String message) { + public ApiErrorResponse(final String requestType, final String message, final ApiErrorCause[] causes) { this.message = message; this.requestType = requestType; + this.causes = causes; } public boolean isError() { @@ -52,12 +58,55 @@ public String getRequestType() { return requestType; } + public ApiErrorCause[] getCauses() { + return causes; + } + @Override public String toString() { return "ApiErrorResponse{" + "error=" + error + ", message='" + message + '\'' + ", requestType='" + requestType + '\'' + + ", causes=" + Arrays.toString(causes) + '}'; } + + /** + * Utility method to generate underlying ApiErrorCause array from exception. + * @param exception exception. + * @return Array of ApiErrorCauses. + */ + public static ApiErrorCause[] buildCauseList(final Exception exception) { + if (exception == null) { + return new ApiErrorCause[0]; + } + + final List causeList = new ArrayList<>(); + Throwable cause = exception.getCause(); + while (cause != null) { + final StackTraceElement[] trace = cause.getStackTrace(); + String file = ""; + String method = ""; + int line = 0; + + if (trace.length > 0) { + file = trace[0].getFileName(); + method = trace[0].getClassName() + "::" + trace[0].getMethodName(); + line = trace[0].getLineNumber(); + } + + causeList.add(new ApiErrorCause( + cause.getClass().getName(), + cause.getMessage(), + file, + method, + line + )); + + // Continue loop. + cause = cause.getCause(); + } + return causeList.toArray(new ApiErrorCause[0]); + } }