From 994fa3096f82eee04e9107d1673ab8fc3c9a0751 Mon Sep 17 00:00:00 2001 From: Stephen Powis Date: Wed, 11 Apr 2018 17:52:38 +0900 Subject: [PATCH 1/3] Make class public --- .../kafka/connect/apiclient/request/dto/ConnectorStatus.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/sourcelab/kafka/connect/apiclient/request/dto/ConnectorStatus.java b/src/main/java/org/sourcelab/kafka/connect/apiclient/request/dto/ConnectorStatus.java index 6f92dd7..9922309 100644 --- a/src/main/java/org/sourcelab/kafka/connect/apiclient/request/dto/ConnectorStatus.java +++ b/src/main/java/org/sourcelab/kafka/connect/apiclient/request/dto/ConnectorStatus.java @@ -52,7 +52,7 @@ public String toString() { /** * Defines the status of a Task. */ - private static final class TaskStatus { + public static final class TaskStatus { private int id; private String state; private String workerId; From bd6fc4f1b5e84764fc56fb33fbd8c02feb641424 Mon Sep 17 00:00:00 2001 From: Stephen Powis Date: Wed, 11 Apr 2018 17:54:48 +0900 Subject: [PATCH 2/3] reduce log level to debug --- .../kafka/connect/apiclient/KafkaConnectClient.java | 2 +- .../connect/apiclient/rest/HttpClientRestClient.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/sourcelab/kafka/connect/apiclient/KafkaConnectClient.java b/src/main/java/org/sourcelab/kafka/connect/apiclient/KafkaConnectClient.java index 14b2adc..5179072 100644 --- a/src/main/java/org/sourcelab/kafka/connect/apiclient/KafkaConnectClient.java +++ b/src/main/java/org/sourcelab/kafka/connect/apiclient/KafkaConnectClient.java @@ -272,7 +272,7 @@ private T submitRequest(final Request request) { String responseStr = restResponse.getResponseStr(); // If we have a valid response - logger.info("Response: {}", restResponse); + logger.debug("Response: {}", restResponse); // Check for invalid http status codes if (responseCode >= 200 && responseCode < 300) { diff --git a/src/main/java/org/sourcelab/kafka/connect/apiclient/rest/HttpClientRestClient.java b/src/main/java/org/sourcelab/kafka/connect/apiclient/rest/HttpClientRestClient.java index c989fee..59875f0 100644 --- a/src/main/java/org/sourcelab/kafka/connect/apiclient/rest/HttpClientRestClient.java +++ b/src/main/java/org/sourcelab/kafka/connect/apiclient/rest/HttpClientRestClient.java @@ -211,7 +211,7 @@ private T submitGetRequest(final String url, final Map getPa // Conditionally add content-type header? get.addHeader(new BasicHeader("Content-Type", "application/json")); - logger.info("Executing request {}", get.getRequestLine()); + logger.debug("Executing request {}", get.getRequestLine()); // Execute and return return httpClient.execute(get, responseHandler); @@ -253,7 +253,7 @@ private T submitPostRequest(final String url, final Object requestBody, fina post.setEntity(new StringEntity(jsonPayloadStr)); - logger.info("Executing request {} with {}", post.getRequestLine(), jsonPayloadStr); + logger.debug("Executing request {} with {}", post.getRequestLine(), jsonPayloadStr); // Execute and return return httpClient.execute(post, responseHandler); @@ -292,7 +292,7 @@ private T submitPutRequest(final String url, final Object requestBody, final final String jsonPayloadStr = JacksonFactory.newInstance().writeValueAsString(requestBody); put.setEntity(new StringEntity(jsonPayloadStr)); - logger.info("Executing request {} with {}", put.getRequestLine(), jsonPayloadStr); + logger.debug("Executing request {} with {}", put.getRequestLine(), jsonPayloadStr); // Execute and return return httpClient.execute(put, responseHandler); @@ -336,7 +336,7 @@ private T submitDeleteRequest(final String url, final Object requestBody, fi // Convert to Json final String jsonPayloadStr = JacksonFactory.newInstance().writeValueAsString(requestBody); - logger.info("Executing request {} with {}", delete.getRequestLine(), jsonPayloadStr); + logger.debug("Executing request {} with {}", delete.getRequestLine(), jsonPayloadStr); // Execute and return return httpClient.execute(delete, responseHandler); From 0da1b2967bc115a5bf6c2cdeba481dcade073386 Mon Sep 17 00:00:00 2001 From: Stephen Powis Date: Thu, 12 Apr 2018 15:46:22 +0900 Subject: [PATCH 3/3] Add new exception classes, mark classes as not final --- CHANGELOG.md | 8 ++- .../connect/apiclient/KafkaConnectClient.java | 4 +- .../request/dto/ConnectorDefinition.java | 2 +- .../request/dto/ConnectorStatus.java | 4 +- ...oncurrentConfigModificationException.java} | 25 +++----- .../exceptions/InvalidRequestException.java | 64 +++++++++++++++++++ .../exceptions/ResourceNotFoundException.java | 32 ++++++++++ .../rest/handlers/RestResponseHandler.java | 2 +- 8 files changed, 117 insertions(+), 24 deletions(-) rename src/main/java/org/sourcelab/kafka/connect/apiclient/rest/{InvalidRequestException.java => exceptions/ConcurrentConfigModificationException.java} (68%) create mode 100644 src/main/java/org/sourcelab/kafka/connect/apiclient/rest/exceptions/InvalidRequestException.java create mode 100644 src/main/java/org/sourcelab/kafka/connect/apiclient/rest/exceptions/ResourceNotFoundException.java diff --git a/CHANGELOG.md b/CHANGELOG.md index b27deb4..7c8789f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## 1.0.1 (04/05/18) +## 1.0.2 (04/12/2018) +- More specific exception classes thrown when requests fail. +- Mark internal classes as not final to allow mocking more easily. + +## 1.0.1 (04/05/2018) - Update Jackson dependency to 2.9.5 [CVE-2018-7489](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-7489). -## 1.0.0 (03/01/18) +## 1.0.0 (03/01/2018) - Initial release! \ No newline at end of file diff --git a/src/main/java/org/sourcelab/kafka/connect/apiclient/KafkaConnectClient.java b/src/main/java/org/sourcelab/kafka/connect/apiclient/KafkaConnectClient.java index 5179072..4115f6e 100644 --- a/src/main/java/org/sourcelab/kafka/connect/apiclient/KafkaConnectClient.java +++ b/src/main/java/org/sourcelab/kafka/connect/apiclient/KafkaConnectClient.java @@ -46,7 +46,7 @@ import org.sourcelab.kafka.connect.apiclient.request.put.PutConnectorPluginConfigValidate; import org.sourcelab.kafka.connect.apiclient.request.put.PutConnectorResume; import org.sourcelab.kafka.connect.apiclient.rest.HttpClientRestClient; -import org.sourcelab.kafka.connect.apiclient.rest.InvalidRequestException; +import org.sourcelab.kafka.connect.apiclient.rest.exceptions.InvalidRequestException; import org.sourcelab.kafka.connect.apiclient.rest.RestClient; import org.sourcelab.kafka.connect.apiclient.rest.RestResponse; @@ -292,7 +292,7 @@ private T submitRequest(final Request request) { // Attempt to parse error response try { final RequestErrorResponse errorResponse = JacksonFactory.newInstance().readValue(responseStr, RequestErrorResponse.class); - throw new InvalidRequestException(errorResponse.getMessage(), errorResponse.getErrorCode()); + throw InvalidRequestException.factory(errorResponse); } catch (final IOException e) { // swallow } diff --git a/src/main/java/org/sourcelab/kafka/connect/apiclient/request/dto/ConnectorDefinition.java b/src/main/java/org/sourcelab/kafka/connect/apiclient/request/dto/ConnectorDefinition.java index d5c4b46..311e945 100644 --- a/src/main/java/org/sourcelab/kafka/connect/apiclient/request/dto/ConnectorDefinition.java +++ b/src/main/java/org/sourcelab/kafka/connect/apiclient/request/dto/ConnectorDefinition.java @@ -58,7 +58,7 @@ public String toString() { /** * Represents a Task. */ - private static final class TaskDefinition { + public static final class TaskDefinition { private String connector; private int task; diff --git a/src/main/java/org/sourcelab/kafka/connect/apiclient/request/dto/ConnectorStatus.java b/src/main/java/org/sourcelab/kafka/connect/apiclient/request/dto/ConnectorStatus.java index 9922309..6a9bf58 100644 --- a/src/main/java/org/sourcelab/kafka/connect/apiclient/request/dto/ConnectorStatus.java +++ b/src/main/java/org/sourcelab/kafka/connect/apiclient/request/dto/ConnectorStatus.java @@ -23,7 +23,7 @@ /** * Represents the status of a deployed connector. */ -public final class ConnectorStatus { +public class ConnectorStatus { private String name; private Map connector; private List tasks; @@ -52,7 +52,7 @@ public String toString() { /** * Defines the status of a Task. */ - public static final class TaskStatus { + public static class TaskStatus { private int id; private String state; private String workerId; diff --git a/src/main/java/org/sourcelab/kafka/connect/apiclient/rest/InvalidRequestException.java b/src/main/java/org/sourcelab/kafka/connect/apiclient/rest/exceptions/ConcurrentConfigModificationException.java similarity index 68% rename from src/main/java/org/sourcelab/kafka/connect/apiclient/rest/InvalidRequestException.java rename to src/main/java/org/sourcelab/kafka/connect/apiclient/rest/exceptions/ConcurrentConfigModificationException.java index 9d243f0..734ddfb 100644 --- a/src/main/java/org/sourcelab/kafka/connect/apiclient/rest/InvalidRequestException.java +++ b/src/main/java/org/sourcelab/kafka/connect/apiclient/rest/exceptions/ConcurrentConfigModificationException.java @@ -15,25 +15,18 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package org.sourcelab.kafka.connect.apiclient.rest; +package org.sourcelab.kafka.connect.apiclient.rest.exceptions; /** - * Represents when a request is invalid. + * Represents when a request is rejected due to concurrent configuration modification. */ -public class InvalidRequestException extends RuntimeException { - private final int errorCode; +public class ConcurrentConfigModificationException extends InvalidRequestException { - public InvalidRequestException(final String message, final int errorCode) { - super(message); - this.errorCode = errorCode; - } - - public InvalidRequestException(final String message, final Throwable cause) { - super(message, cause); - this.errorCode = -1; - } - - public int getErrorCode() { - return errorCode; + /** + * Contructor. + * @param message Error message. + */ + public ConcurrentConfigModificationException(String message) { + super(message, 409); } } diff --git a/src/main/java/org/sourcelab/kafka/connect/apiclient/rest/exceptions/InvalidRequestException.java b/src/main/java/org/sourcelab/kafka/connect/apiclient/rest/exceptions/InvalidRequestException.java new file mode 100644 index 0000000..c1dee64 --- /dev/null +++ b/src/main/java/org/sourcelab/kafka/connect/apiclient/rest/exceptions/InvalidRequestException.java @@ -0,0 +1,64 @@ +/** + * Copyright 2018 SourceLab.org https://github.com/SourceLabOrg/kafka-connect-client + * + * 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.connect.apiclient.rest.exceptions; + +import com.google.common.base.Preconditions; +import org.sourcelab.kafka.connect.apiclient.request.RequestErrorResponse; + +/** + * Represents when a request is invalid. + */ +public class InvalidRequestException extends RuntimeException { + private final int errorCode; + + /** + * Constructor. + * @param message Error message. + * @param errorCode Http Error Code. + */ + public InvalidRequestException(final String message, final int errorCode) { + super(message); + this.errorCode = errorCode; + } + + /** + * @return Http Error Code. + */ + public int getErrorCode() { + return errorCode; + } + + /** + * Factory method to create proper exception class based on the error. + * @param errorResponse Parsed error response from server. + * @return Appropriate Exception class. + */ + public static InvalidRequestException factory(final RequestErrorResponse errorResponse) { + Preconditions.checkNotNull(errorResponse, "Invalid RequestErrorResponse parameter, must not be null"); + + switch (errorResponse.getErrorCode()) { + case 404: + return new ResourceNotFoundException(errorResponse.getMessage()); + case 409: + return new ConcurrentConfigModificationException(errorResponse.getMessage()); + default: + return new InvalidRequestException(errorResponse.getMessage(), errorResponse.getErrorCode()); + + } + } +} diff --git a/src/main/java/org/sourcelab/kafka/connect/apiclient/rest/exceptions/ResourceNotFoundException.java b/src/main/java/org/sourcelab/kafka/connect/apiclient/rest/exceptions/ResourceNotFoundException.java new file mode 100644 index 0000000..6034239 --- /dev/null +++ b/src/main/java/org/sourcelab/kafka/connect/apiclient/rest/exceptions/ResourceNotFoundException.java @@ -0,0 +1,32 @@ +/** + * Copyright 2018 SourceLab.org https://github.com/SourceLabOrg/kafka-connect-client + * + * 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.connect.apiclient.rest.exceptions; + +/** + * Represents when a request is rejected due because the resource is unable to be located. + */ +public class ResourceNotFoundException extends InvalidRequestException { + + /** + * Constructor. + * @param message Error message. + */ + public ResourceNotFoundException(String message) { + super(message, 404); + } +} diff --git a/src/main/java/org/sourcelab/kafka/connect/apiclient/rest/handlers/RestResponseHandler.java b/src/main/java/org/sourcelab/kafka/connect/apiclient/rest/handlers/RestResponseHandler.java index 9301d10..7bb2cb0 100644 --- a/src/main/java/org/sourcelab/kafka/connect/apiclient/rest/handlers/RestResponseHandler.java +++ b/src/main/java/org/sourcelab/kafka/connect/apiclient/rest/handlers/RestResponseHandler.java @@ -48,7 +48,7 @@ public RestResponse handleResponse(final HttpResponse response) { return new RestResponse(responseStr, statusCode); } catch (final IOException exception) { logger.error("Failed to read entity: {}", exception.getMessage(), exception); - // TODO throw exception + // TODO throw exceptions return null; } }