diff --git a/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/RetrofitException.java b/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/RetrofitException.java deleted file mode 100644 index 29cbab1ea..000000000 --- a/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/RetrofitException.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2023 OpsMx, Inc. - * - * Licensed 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 com.netflix.spinnaker.kork.retrofit.exceptions; - -import java.io.IOException; -import java.lang.annotation.Annotation; -import java.util.Objects; -import okhttp3.ResponseBody; -import retrofit2.Converter; -import retrofit2.Response; -import retrofit2.Retrofit; - -/** - * The {@link RetrofitException} class is similar to {@link retrofit.RetrofitError} as RetrofitError - * class is removed in retrofit2. To handle the exception globally and achieve similar logic as - * retrofit in retrofit2, this exception used along with {@link - * com.netflix.spinnaker.kork.retrofit.ErrorHandlingExecutorCallAdapterFactory}. - */ -public class RetrofitException extends RuntimeException { - public static RetrofitException httpError(Response response, Retrofit retrofit) { - String message = response.code() + " " + response.message(); - return new RetrofitException(message, response, retrofit); - } - - /** Response from server, which contains causes for the failure */ - private final Response response; - - /** - * Client used while the service creation, which has convertor logic to be used to parse the - * response - */ - private final Retrofit retrofit; - - RetrofitException(String message, Response response, Retrofit retrofit) { - super(message); - - this.response = response; - if (response != null) { - // Fail fast instead of checking for null in e.g. getErrorBodyAs. - Objects.requireNonNull(response.errorBody()); - } - this.retrofit = retrofit; - } - - /** Response object containing status code, headers, body, etc. */ - public Response getResponse() { - return response; - } - - /** - * HTTP response body converted to specified {@code type}. {@code null} if there is no response. - * - * @throws RuntimeException wrapping the underlying IOException if unable to convert the body to - * the specified {@code type}. - */ - public T getErrorBodyAs(Class type) { - if (response == null) { - return null; - } - - Converter converter = retrofit.responseBodyConverter(type, new Annotation[0]); - try { - return converter.convert(response.errorBody()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerHttpException.java b/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerHttpException.java index 0fcd2b8c1..1ee208e76 100644 --- a/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerHttpException.java +++ b/kork-retrofit/src/main/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerHttpException.java @@ -31,9 +31,9 @@ /** * An exception that exposes the {@link Response} of a given HTTP {@link RetrofitError} or {@link - * okhttp3.Response} of a {@link RetrofitException} if retrofit 2.x used and a detail message that - * extracts useful information from the {@link Response} or {@link okhttp3.Response}. Both {@link - * Response} and {@link okhttp3.Response} can't be set together.. + * okhttp3.Response} if retrofit 2.x used and a detail message that extracts useful information from + * the {@link Response} or {@link okhttp3.Response}. Both {@link Response} and {@link + * okhttp3.Response} can't be set together.. */ @NonnullByDefault public class SpinnakerHttpException extends SpinnakerServerException { @@ -49,17 +49,14 @@ public class SpinnakerHttpException extends SpinnakerServerException { private final String rawMessage; private final Map responseBody; - private retrofit2.Retrofit retrofit; - - private static Map jsonErrorResponseBody = - Map.of("message", "failed to parse response"); + private final retrofit2.Retrofit retrofit; public SpinnakerHttpException(RetrofitError e) { super(e); this.response = e.getResponse(); this.retrofit2Response = null; + this.retrofit = null; responseBody = (Map) e.getBodyAs(HashMap.class); - this.rawMessage = responseBody != null ? (String) responseBody.getOrDefault("message", e.getMessage()) @@ -96,28 +93,28 @@ public SpinnakerHttpException(String message, SpinnakerHttpException cause) { this.retrofit2Response = cause.retrofit2Response; rawMessage = null; this.responseBody = cause.responseBody; + this.retrofit = null; } /** * The constructor handles the HTTP retrofit2 exception, similar to retrofit logic. It is used * with {@link com.netflix.spinnaker.kork.retrofit.ErrorHandlingExecutorCallAdapterFactory}. */ - public SpinnakerHttpException(retrofit2.Response syncResp, retrofit2.Retrofit retrofit) { - super( - syncResp.code() + " " + syncResp.message(), - new Throwable(syncResp.code() + " " + syncResp.message())); - this.retrofit2Response = syncResp; + public SpinnakerHttpException( + retrofit2.Response retrofit2Response, retrofit2.Retrofit retrofit) { + super(new Throwable(retrofit2Response.code() + " " + retrofit2Response.message())); + this.retrofit2Response = retrofit2Response; this.response = null; this.retrofit = retrofit; - responseBody = this.getErrorBodyAs(); - this.rawMessage = - responseBody != null - ? (String) responseBody.getOrDefault("message", getMessage()) - : getMessage(); if ((retrofit2Response.code() == HttpStatus.NOT_FOUND.value()) || (retrofit2Response.code() == HttpStatus.BAD_REQUEST.value())) { setRetryable(false); } + responseBody = (Map) this.getErrorBodyAs(HashMap.class); + this.rawMessage = + responseBody != null + ? (String) responseBody.getOrDefault("message", getMessage()) + : getMessage(); } public int getResponseCode() { @@ -178,17 +175,16 @@ public Map getResponseBody() { return this.responseBody; } - private Map getErrorBodyAs() { + public T getErrorBodyAs(Class type) { if (retrofit2Response == null) { return null; } - Converter converter = - retrofit.responseBodyConverter(Map.class, new Annotation[0]); + Converter converter = retrofit.responseBodyConverter(type, new Annotation[0]); try { return converter.convert(retrofit2Response.errorBody()); } catch (IOException e) { - return jsonErrorResponseBody; + throw new RuntimeException(e); } } } diff --git a/kork-retrofit/src/test/java/com/netflix/spinnaker/kork/retrofit/exceptions/RetrofitExceptionTest.java b/kork-retrofit/src/test/java/com/netflix/spinnaker/kork/retrofit/exceptions/RetrofitExceptionTest.java deleted file mode 100644 index 3e5ccd8d6..000000000 --- a/kork-retrofit/src/test/java/com/netflix/spinnaker/kork/retrofit/exceptions/RetrofitExceptionTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2023 OpsMx, Inc. - * - * Licensed 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 com.netflix.spinnaker.kork.retrofit.exceptions; - -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import okhttp3.MediaType; -import okhttp3.ResponseBody; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.springframework.http.HttpStatus; -import retrofit2.Response; -import retrofit2.Retrofit; -import retrofit2.converter.jackson.JacksonConverterFactory; - -public class RetrofitExceptionTest { - - private static Retrofit retrofit2Service; - - private final String validJsonResponseBodyString = "{\"name\":\"test\"}"; - - @BeforeAll - public static void setupOnce() { - retrofit2Service = - new Retrofit.Builder() - .baseUrl("http://localhost:8987/") - .addConverterFactory(JacksonConverterFactory.create()) - .build(); - } - - @Test - public void testRetrofitExceptionRequiresErrorBody() { - ResponseBody responseBody = - ResponseBody.create( - MediaType.parse("application/json" + "; charset=utf-8"), validJsonResponseBodyString); - - // We get a null error body for 200-OK successful response, - // which we can use to check a RetrofitException instance creation. - Response response = Response.success(HttpStatus.OK.value(), responseBody); - assertNull(response.errorBody()); - - assertThrows( - NullPointerException.class, () -> RetrofitException.httpError(response, retrofit2Service)); - } -} diff --git a/kork-retrofit/src/test/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerServerExceptionTest.java b/kork-retrofit/src/test/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerServerExceptionTest.java index 3a2fbb8dd..e6759b4f6 100644 --- a/kork-retrofit/src/test/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerServerExceptionTest.java +++ b/kork-retrofit/src/test/java/com/netflix/spinnaker/kork/retrofit/exceptions/SpinnakerServerExceptionTest.java @@ -112,7 +112,7 @@ public void testSpinnakerHttpExceptionFromRetrofitException() { "Status: %s, URL: %s, Message: %s", HttpStatus.NOT_FOUND.value(), "http://localhost/", - HttpStatus.NOT_FOUND.value() + " " + "Response.error()"); + "java.lang.Throwable:" + " " + HttpStatus.NOT_FOUND.value() + " " + "Response.error()"); assertEquals(expectedMessage, notFoundException.getMessage()); } }