From 94365cf348f5308cf07d9b784ac5c5cf15b32cde Mon Sep 17 00:00:00 2001 From: Justintime50 <39606064+Justintime50@users.noreply.github.com> Date: Tue, 25 Feb 2025 10:49:36 -0700 Subject: [PATCH 1/7] feat: deserialize alternative format errors --- .../exception/API/BadRequestError.java | 6 +- .../exception/API/ForbiddenError.java | 6 +- .../exception/API/GatewayTimeoutError.java | 6 +- .../exception/API/InternalServerError.java | 6 +- .../exception/API/InvalidRequestError.java | 6 +- .../exception/API/MethodNotAllowedError.java | 6 +- .../easypost/exception/API/NotFoundError.java | 6 +- .../easypost/exception/API/PaymentError.java | 6 +- .../exception/API/RateLimitError.java | 6 +- .../easypost/exception/API/RedirectError.java | 6 +- .../API/ServiceUnavailableError.java | 6 +- .../easypost/exception/API/TimeoutError.java | 6 +- .../exception/API/UnauthorizedError.java | 6 +- .../exception/API/UnknownApiError.java | 6 +- .../com/easypost/exception/APIException.java | 19 +--- .../easypost/exception/EasyPostException.java | 8 -- .../com/easypost/http/EasyPostResponse.java | 8 -- .../java/com/easypost/http/Requestor.java | 11 +-- .../com/easypost/model/EasyPostResource.java | 8 -- src/main/java/com/easypost/model/Error.java | 25 +++-- .../java/com/easypost/model/FieldError.java | 39 ++++++++ .../model/FieldErrorOrStringList.java | 53 +++++++++++ .../error/error_alternative_format.json | 91 +++++++++++++++++++ src/test/java/com/easypost/ErrorTest.java | 23 ++++- 24 files changed, 252 insertions(+), 117 deletions(-) create mode 100644 src/main/java/com/easypost/model/FieldError.java create mode 100644 src/main/java/com/easypost/model/FieldErrorOrStringList.java create mode 100644 src/test/cassettes/error/error_alternative_format.json diff --git a/src/main/java/com/easypost/exception/API/BadRequestError.java b/src/main/java/com/easypost/exception/API/BadRequestError.java index 4bb1b31da..c13cad97c 100644 --- a/src/main/java/com/easypost/exception/API/BadRequestError.java +++ b/src/main/java/com/easypost/exception/API/BadRequestError.java @@ -1,8 +1,6 @@ package com.easypost.exception.API; -import java.util.List; - -import com.easypost.model.Error; +import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; public class BadRequestError extends APIException { @@ -14,7 +12,7 @@ public class BadRequestError extends APIException { * @param statusCode the exception status code * @param errors the errors array */ - public BadRequestError(final String message, final String code, final int statusCode, List errors) { + public BadRequestError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { super(message, code, statusCode, errors); } } diff --git a/src/main/java/com/easypost/exception/API/ForbiddenError.java b/src/main/java/com/easypost/exception/API/ForbiddenError.java index 4f5d9070e..d6f631f37 100644 --- a/src/main/java/com/easypost/exception/API/ForbiddenError.java +++ b/src/main/java/com/easypost/exception/API/ForbiddenError.java @@ -1,8 +1,6 @@ package com.easypost.exception.API; -import java.util.List; - -import com.easypost.model.Error; +import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; public class ForbiddenError extends APIException { @@ -14,7 +12,7 @@ public class ForbiddenError extends APIException { * @param statusCode the exception status code * @param errors the errors array */ - public ForbiddenError(final String message, final String code, final int statusCode, List errors) { + public ForbiddenError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { super(message, code, statusCode, errors); } } diff --git a/src/main/java/com/easypost/exception/API/GatewayTimeoutError.java b/src/main/java/com/easypost/exception/API/GatewayTimeoutError.java index ab42e2015..b9ad38b9a 100644 --- a/src/main/java/com/easypost/exception/API/GatewayTimeoutError.java +++ b/src/main/java/com/easypost/exception/API/GatewayTimeoutError.java @@ -1,8 +1,6 @@ package com.easypost.exception.API; -import java.util.List; - -import com.easypost.model.Error; +import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; public class GatewayTimeoutError extends APIException { @@ -14,7 +12,7 @@ public class GatewayTimeoutError extends APIException { * @param statusCode the exception status code * @param errors the errors array */ - public GatewayTimeoutError(final String message, final String code, final int statusCode, List errors) { + public GatewayTimeoutError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { super(message, code, statusCode, errors); } } diff --git a/src/main/java/com/easypost/exception/API/InternalServerError.java b/src/main/java/com/easypost/exception/API/InternalServerError.java index fff3980bd..8c2ae88c5 100644 --- a/src/main/java/com/easypost/exception/API/InternalServerError.java +++ b/src/main/java/com/easypost/exception/API/InternalServerError.java @@ -1,8 +1,6 @@ package com.easypost.exception.API; -import java.util.List; - -import com.easypost.model.Error; +import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; public class InternalServerError extends APIException { @@ -14,7 +12,7 @@ public class InternalServerError extends APIException { * @param statusCode the exception status code * @param errors the errors array */ - public InternalServerError(final String message, final String code, final int statusCode, List errors) { + public InternalServerError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { super(message, code, statusCode, errors); } } diff --git a/src/main/java/com/easypost/exception/API/InvalidRequestError.java b/src/main/java/com/easypost/exception/API/InvalidRequestError.java index 26d32a77f..4fd4bae67 100644 --- a/src/main/java/com/easypost/exception/API/InvalidRequestError.java +++ b/src/main/java/com/easypost/exception/API/InvalidRequestError.java @@ -1,8 +1,6 @@ package com.easypost.exception.API; -import java.util.List; - -import com.easypost.model.Error; +import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; public class InvalidRequestError extends APIException { @@ -14,7 +12,7 @@ public class InvalidRequestError extends APIException { * @param statusCode the exception status code * @param errors the errors array */ - public InvalidRequestError(final String message, final String code, final int statusCode, List errors) { + public InvalidRequestError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { super(message, code, statusCode, errors); } } diff --git a/src/main/java/com/easypost/exception/API/MethodNotAllowedError.java b/src/main/java/com/easypost/exception/API/MethodNotAllowedError.java index 719b40169..6adce0935 100644 --- a/src/main/java/com/easypost/exception/API/MethodNotAllowedError.java +++ b/src/main/java/com/easypost/exception/API/MethodNotAllowedError.java @@ -1,8 +1,6 @@ package com.easypost.exception.API; -import java.util.List; - -import com.easypost.model.Error; +import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; public class MethodNotAllowedError extends APIException { @@ -14,7 +12,7 @@ public class MethodNotAllowedError extends APIException { * @param statusCode the exception status code * @param errors the errors array */ - public MethodNotAllowedError(final String message, final String code, final int statusCode, List errors) { + public MethodNotAllowedError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { super(message, code, statusCode, errors); } } diff --git a/src/main/java/com/easypost/exception/API/NotFoundError.java b/src/main/java/com/easypost/exception/API/NotFoundError.java index 688aa142c..b57007c38 100644 --- a/src/main/java/com/easypost/exception/API/NotFoundError.java +++ b/src/main/java/com/easypost/exception/API/NotFoundError.java @@ -1,8 +1,6 @@ package com.easypost.exception.API; -import java.util.List; - -import com.easypost.model.Error; +import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; public class NotFoundError extends APIException { @@ -14,7 +12,7 @@ public class NotFoundError extends APIException { * @param statusCode the exception status code * @param errors the errors array */ - public NotFoundError(final String message, final String code, final int statusCode, List errors) { + public NotFoundError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { super(message, code, statusCode, errors); } } diff --git a/src/main/java/com/easypost/exception/API/PaymentError.java b/src/main/java/com/easypost/exception/API/PaymentError.java index c1dddde13..e1299b3c6 100644 --- a/src/main/java/com/easypost/exception/API/PaymentError.java +++ b/src/main/java/com/easypost/exception/API/PaymentError.java @@ -1,8 +1,6 @@ package com.easypost.exception.API; -import java.util.List; - -import com.easypost.model.Error; +import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; public class PaymentError extends APIException { @@ -14,7 +12,7 @@ public class PaymentError extends APIException { * @param statusCode the exception status code * @param errors the errors array */ - public PaymentError(final String message, final String code, final int statusCode, List errors) { + public PaymentError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { super(message, code, statusCode, errors); } } diff --git a/src/main/java/com/easypost/exception/API/RateLimitError.java b/src/main/java/com/easypost/exception/API/RateLimitError.java index 896a417a8..fcb961a74 100644 --- a/src/main/java/com/easypost/exception/API/RateLimitError.java +++ b/src/main/java/com/easypost/exception/API/RateLimitError.java @@ -1,8 +1,6 @@ package com.easypost.exception.API; -import java.util.List; - -import com.easypost.model.Error; +import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; public class RateLimitError extends APIException { @@ -14,7 +12,7 @@ public class RateLimitError extends APIException { * @param statusCode the exception status code * @param errors the errors array */ - public RateLimitError(final String message, final String code, final int statusCode, List errors) { + public RateLimitError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { super(message, code, statusCode, errors); } } diff --git a/src/main/java/com/easypost/exception/API/RedirectError.java b/src/main/java/com/easypost/exception/API/RedirectError.java index c00ad1ef1..bebf74908 100644 --- a/src/main/java/com/easypost/exception/API/RedirectError.java +++ b/src/main/java/com/easypost/exception/API/RedirectError.java @@ -1,8 +1,6 @@ package com.easypost.exception.API; -import java.util.List; - -import com.easypost.model.Error; +import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; public class RedirectError extends APIException { @@ -14,7 +12,7 @@ public class RedirectError extends APIException { * @param statusCode the exception status code * @param errors the errors array */ - public RedirectError(final String message, final String code, final int statusCode, List errors) { + public RedirectError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { super(message, code, statusCode, errors); } } diff --git a/src/main/java/com/easypost/exception/API/ServiceUnavailableError.java b/src/main/java/com/easypost/exception/API/ServiceUnavailableError.java index 0756428b0..12524046b 100644 --- a/src/main/java/com/easypost/exception/API/ServiceUnavailableError.java +++ b/src/main/java/com/easypost/exception/API/ServiceUnavailableError.java @@ -1,8 +1,6 @@ package com.easypost.exception.API; -import java.util.List; - -import com.easypost.model.Error; +import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; public class ServiceUnavailableError extends APIException { @@ -14,7 +12,7 @@ public class ServiceUnavailableError extends APIException { * @param statusCode the exception status code * @param errors the errors array */ - public ServiceUnavailableError(final String message, final String code, final int statusCode, List errors) { + public ServiceUnavailableError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { super(message, code, statusCode, errors); } } diff --git a/src/main/java/com/easypost/exception/API/TimeoutError.java b/src/main/java/com/easypost/exception/API/TimeoutError.java index 28993acfe..517644bcf 100644 --- a/src/main/java/com/easypost/exception/API/TimeoutError.java +++ b/src/main/java/com/easypost/exception/API/TimeoutError.java @@ -1,8 +1,6 @@ package com.easypost.exception.API; -import java.util.List; - -import com.easypost.model.Error; +import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; public class TimeoutError extends APIException { @@ -14,7 +12,7 @@ public class TimeoutError extends APIException { * @param statusCode the exception status code * @param errors the errors array */ - public TimeoutError(final String message, final String code, final int statusCode, List errors) { + public TimeoutError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { super(message, code, statusCode, errors); } } diff --git a/src/main/java/com/easypost/exception/API/UnauthorizedError.java b/src/main/java/com/easypost/exception/API/UnauthorizedError.java index 1434cc183..7719082e3 100644 --- a/src/main/java/com/easypost/exception/API/UnauthorizedError.java +++ b/src/main/java/com/easypost/exception/API/UnauthorizedError.java @@ -1,8 +1,6 @@ package com.easypost.exception.API; -import java.util.List; - -import com.easypost.model.Error; +import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; public class UnauthorizedError extends APIException { @@ -14,7 +12,7 @@ public class UnauthorizedError extends APIException { * @param statusCode the exception status code * @param errors the errors array */ - public UnauthorizedError(final String message, final String code, final int statusCode, List errors) { + public UnauthorizedError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { super(message, code, statusCode, errors); } } diff --git a/src/main/java/com/easypost/exception/API/UnknownApiError.java b/src/main/java/com/easypost/exception/API/UnknownApiError.java index 423464ac1..d4867b4b1 100644 --- a/src/main/java/com/easypost/exception/API/UnknownApiError.java +++ b/src/main/java/com/easypost/exception/API/UnknownApiError.java @@ -1,8 +1,6 @@ package com.easypost.exception.API; -import java.util.List; - -import com.easypost.model.Error; +import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; public class UnknownApiError extends APIException { @@ -14,7 +12,7 @@ public class UnknownApiError extends APIException { * @param statusCode the exception status code * @param errors the errors array */ - public UnknownApiError(final String message, final String code, final int statusCode, List errors) { + public UnknownApiError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { super(message, code, statusCode, errors); } } diff --git a/src/main/java/com/easypost/exception/APIException.java b/src/main/java/com/easypost/exception/APIException.java index 5bed1bed8..30befd359 100644 --- a/src/main/java/com/easypost/exception/APIException.java +++ b/src/main/java/com/easypost/exception/APIException.java @@ -1,23 +1,14 @@ -/** - * APIException.java - * This file is a part of EasyPost API SDK. - * (c) 2022 EasyPost - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - package com.easypost.exception; +import com.easypost.model.FieldErrorOrStringList; import com.easypost.model.Error; -import java.util.List; - public class APIException extends EasyPostException { private static final long serialVersionUID = 1L; private final String code; private final Integer statusCode; private final String message; - private final List errors; + private final FieldErrorOrStringList errors; /** * APIException constructor. @@ -46,7 +37,7 @@ public APIException(final String message, final Throwable ex) { * @param statusCode the exception status code * @param errors the errors array */ - public APIException(final String message, final String code, final int statusCode, final List errors) { + public APIException(final String message, final String code, final int statusCode, final FieldErrorOrStringList errors) { this(message, code, statusCode, errors, null); } @@ -60,7 +51,7 @@ public APIException(final String message, final String code, final int statusCod * @param ex the exception cause */ public APIException(final String message, final String code, final Integer statusCode, - final List errors, final Throwable ex) { + final FieldErrorOrStringList errors, final Throwable ex) { super(message); this.code = code; this.statusCode = statusCode; @@ -101,7 +92,7 @@ public String getMessage() { * * @return errors of the exception */ - public List getErrors() { + public FieldErrorOrStringList getErrors() { return errors; } } diff --git a/src/main/java/com/easypost/exception/EasyPostException.java b/src/main/java/com/easypost/exception/EasyPostException.java index 47c2ff59f..2e396ad41 100644 --- a/src/main/java/com/easypost/exception/EasyPostException.java +++ b/src/main/java/com/easypost/exception/EasyPostException.java @@ -1,11 +1,3 @@ -/** - * EasyPostException.java - * This file is a part of EasyPost API SDK. - * (c) 2022 EasyPost - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - package com.easypost.exception; public class EasyPostException extends Exception { diff --git a/src/main/java/com/easypost/http/EasyPostResponse.java b/src/main/java/com/easypost/http/EasyPostResponse.java index 65a84cbf4..b1864924f 100644 --- a/src/main/java/com/easypost/http/EasyPostResponse.java +++ b/src/main/java/com/easypost/http/EasyPostResponse.java @@ -1,11 +1,3 @@ -/** - * EasyPostResponse.java - * This file is a part of EasyPost API SDK. - * (c) 2022 EasyPost - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - package com.easypost.http; import lombok.Getter; diff --git a/src/main/java/com/easypost/http/Requestor.java b/src/main/java/com/easypost/http/Requestor.java index 447b1e484..bf8af9e7e 100644 --- a/src/main/java/com/easypost/http/Requestor.java +++ b/src/main/java/com/easypost/http/Requestor.java @@ -1,11 +1,3 @@ -/** - * EasyPostResource.java - * This file is a part of EasyPost API SDK. - * (c) 2022 EasyPost - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - package com.easypost.http; import com.easypost.Constants; @@ -32,6 +24,7 @@ import com.easypost.hooks.ResponseHookResponses; import com.easypost.model.EasyPostResource; import com.easypost.model.Error; +import com.easypost.model.FieldErrorOrStringList; import com.easypost.service.EasyPostClient; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -653,7 +646,7 @@ protected static void handleAPIError(String rBody, final int rCode) Error error = Constants.Http.GSON.fromJson(rBody, Error.class); String errorMessage = error.getMessage(); String errorCode = error.getCode(); - List errors = error.getErrors(); + FieldErrorOrStringList errors = error.getErrors(); if (rCode >= Constants.ErrorCodes.REDIRECT_CODE_BEGIN && rCode <= Constants.ErrorCodes.REDIRECT_CODE_END) { throw new RedirectError(errorMessage, errorCode, rCode, errors); diff --git a/src/main/java/com/easypost/model/EasyPostResource.java b/src/main/java/com/easypost/model/EasyPostResource.java index 4fe9938f6..c8873a936 100644 --- a/src/main/java/com/easypost/model/EasyPostResource.java +++ b/src/main/java/com/easypost/model/EasyPostResource.java @@ -1,11 +1,3 @@ -/** - * EasyPostResource.java - * This file is a part of EasyPost API SDK. - * (c) 2022 EasyPost - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - package com.easypost.model; import java.util.Date; diff --git a/src/main/java/com/easypost/model/Error.java b/src/main/java/com/easypost/model/Error.java index e3b2dfc6f..963c8787e 100644 --- a/src/main/java/com/easypost/model/Error.java +++ b/src/main/java/com/easypost/model/Error.java @@ -1,16 +1,15 @@ package com.easypost.model; -import java.util.List; import lombok.Getter; +import java.util.List; + @Getter @SuppressWarnings("JavaLangClash") public final class Error { private String message; private String code; - private List errors; - private String suggestion; - private String field; + private FieldErrorOrStringList errors; /** * Set the message of this error object. @@ -35,25 +34,25 @@ void setCode(final String code) { * * @param errors The errors. */ - void setErrors(final List errors) { + void setErrors(final FieldErrorOrStringList errors) { this.errors = errors; } /** - * Set the suggestion of this error object. + * Set the errors of this error object from a list of FieldError objects. * - * @param suggestion The suggestion. + * @param errorList The list of FieldError objects. */ - void setSuggestion(final String suggestion) { - this.suggestion = suggestion; + void setErrors(final List errorList) { + this.errors = FieldErrorOrStringList.fromErrorList(errorList); } /** - * Set the field of this error object. + * Set the errors of this error object from a list of strings. * - * @param field The field. + * @param stringList The list of strings. */ - void setField(final String field) { - this.field = field; + void setErrorsFromStringList(final List stringList) { + this.errors = FieldErrorOrStringList.fromStringList(stringList); } } diff --git a/src/main/java/com/easypost/model/FieldError.java b/src/main/java/com/easypost/model/FieldError.java new file mode 100644 index 000000000..6daee0c93 --- /dev/null +++ b/src/main/java/com/easypost/model/FieldError.java @@ -0,0 +1,39 @@ +package com.easypost.model; + +import java.util.List; +import lombok.Getter; + +@Getter +@SuppressWarnings("JavaLangClash") +public final class FieldError { + private String field; + private String message; + private String suggestion; + + /** + * Set the field of this error object. + * + * @param field The field. + */ + void setField(final String field) { + this.field = field; + } + + /** + * Set the message of this error object. + * + * @param message The error message. + */ + void setMessage(final String message) { + this.message = message; + } + + /** + * Set the suggestion of this error object. + * + * @param suggestion The suggestion. + */ + void setSuggestion(final String suggestion) { + this.suggestion = suggestion; + } +} diff --git a/src/main/java/com/easypost/model/FieldErrorOrStringList.java b/src/main/java/com/easypost/model/FieldErrorOrStringList.java new file mode 100644 index 000000000..f65bcd1a0 --- /dev/null +++ b/src/main/java/com/easypost/model/FieldErrorOrStringList.java @@ -0,0 +1,53 @@ +package com.easypost.model; + +import lombok.Getter; + +import java.util.AbstractList; +import java.util.List; + +@Getter +public class FieldErrorOrStringList extends AbstractList { + private final List errorList; + private final List stringList; + + private FieldErrorOrStringList(List errorList, List stringList) { + this.errorList = errorList; + this.stringList = stringList; + } + + public static FieldErrorOrStringList fromErrorList(List errorList) { + return new FieldErrorOrStringList(errorList, null); + } + + public static FieldErrorOrStringList fromStringList(List stringList) { + return new FieldErrorOrStringList(null, stringList); + } + + public boolean isErrorList() { + return errorList != null; + } + + public boolean isStringList() { + return stringList != null; + } + + @Override + public Object get(int index) { + if (isErrorList()) { + return errorList.get(index); + } else if (isStringList()) { + return stringList.get(index); + } + throw new IndexOutOfBoundsException("Index out of bounds or list is empty"); + } + + @Override + public int size() { + if (isErrorList()) { + return errorList.size(); + } else if (isStringList()) { + return stringList.size(); + } + return 0; + } +} diff --git a/src/test/cassettes/error/error_alternative_format.json b/src/test/cassettes/error/error_alternative_format.json new file mode 100644 index 000000000..6faed463c --- /dev/null +++ b/src/test/cassettes/error/error_alternative_format.json @@ -0,0 +1,91 @@ +[ + { + "recordedAt": 1740505524, + "request": { + "body": "{\n \"email_evidence_attachments\": [\n \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAeUlEQVR42mP8//8/AwAI/AL+4Q7AIAAAAABJRU5ErkJggg\\u003d\\u003d\"\n ],\n \"supporting_documentation_attachments\": [\n \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAeUlEQVR42mP8//8/AwAI/AL+4Q7AIAAAAABJRU5ErkJggg\\u003d\\u003d\"\n ],\n \"description\": \"Test description\",\n \"type\": \"damage\",\n \"invoice_attachments\": [\n \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAeUlEQVR42mP8//8/AwAI/AL+4Q7AIAAAAABJRU5ErkJggg\\u003d\\u003d\"\n ],\n \"tracking_code\": \"123\",\n \"contact_email\": \"test@example.com\"\n}", + "method": "POST", + "headers": { + "Accept-Charset": [ + "UTF-8" + ], + "User-Agent": [ + "REDACTED" + ], + "Content-Type": [ + "application/json" + ] + }, + "uri": "https://api.easypost.com/v2/claims" + }, + "response": { + "body": "{\n \"error\": {\n \"code\": \"NOT_FOUND\",\n \"message\": \"The requested resource could not be found.\",\n \"errors\": [\n \"No eligible insurance found with provided tracking code.\"\n ]\n }\n}", + "httpVersion": null, + "headers": { + "null": [ + "HTTP/1.1 404 Not Found" + ], + "content-length": [ + "156" + ], + "expires": [ + "0" + ], + "x-node": [ + "bigweb39nuq" + ], + "x-frame-options": [ + "SAMEORIGIN" + ], + "x-download-options": [ + "noopen" + ], + "x-permitted-cross-domain-policies": [ + "none" + ], + "x-backend": [ + "easypost" + ], + "pragma": [ + "no-cache" + ], + "strict-transport-security": [ + "max-age\u003d31536000; includeSubDomains; preload" + ], + "x-xss-protection": [ + "1; mode\u003dblock" + ], + "x-content-type-options": [ + "nosniff" + ], + "x-ep-request-uuid": [ + "c1c6fbd367be01b4e2b8558f001d4c8a" + ], + "x-proxied": [ + "intlb4nuq 51d74985a2", + "extlb1nuq 99aac35317" + ], + "referrer-policy": [ + "strict-origin-when-cross-origin" + ], + "x-runtime": [ + "0.028904" + ], + "content-type": [ + "application/json; charset\u003dutf-8" + ], + "x-version-label": [ + "easypost-202502251451-d4f6425809-master" + ], + "cache-control": [ + "private, no-cache, no-store" + ] + }, + "status": { + "code": 404, + "message": "Not Found" + }, + "uri": "https://api.easypost.com/v2/claims" + }, + "duration": 130 + } +] \ No newline at end of file diff --git a/src/test/java/com/easypost/ErrorTest.java b/src/test/java/com/easypost/ErrorTest.java index 8cc9b5636..7b9da854a 100644 --- a/src/test/java/com/easypost/ErrorTest.java +++ b/src/test/java/com/easypost/ErrorTest.java @@ -41,7 +41,7 @@ public static void setup() throws EasyPostException { } /** - * Test creating a bad shipment and retrieving errors. + * Tests that we assign properties of an error correctly. * * @throws EasyPostException when the request fails. */ @@ -58,6 +58,27 @@ public void testError() throws EasyPostException { assertEquals("shipment", exception.getErrors().get(0).getField()); } + /** + * Tests that we assign properties of an error correctly when returned via the alternative format. + * NOTE: Claims (among other things) uses the alternative errors format. + * + * @throws EasyPostException when the request fails. + */ + @Test + public void testErrorAlternativeFormat() throws EasyPostException { + vcr.setUpTest("error_alternative_format"); + + HashMap claimData = Fixtures.basicClaim(); + claimData.put("tracking_code", "123"); // Intentionally pass a bad tracking code + + APIException exception = assertThrows(InvalidRequestError.class, () -> vcr.client.claim.create(claimData)); + + assertEquals(404, exception.getStatusCode()); + assertEquals("NOT_FOUND", exception.getCode()); + assertEquals("The requested resource could not be found.", exception.getMessage()); + assertEquals("No eligible insurance found with provided tracking code.", exception.getErrors().get(0)); + } + /** * Test every error type and make sure each error has the correct properties. * From edb1455826a3d949e27717d19597f09d29bf16c4 Mon Sep 17 00:00:00 2001 From: Justintime50 <39606064+Justintime50@users.noreply.github.com> Date: Tue, 25 Feb 2025 12:06:12 -0700 Subject: [PATCH 2/7] fix: ErrorDeserializer --- .../AddressVerificationDeserializer.java | 16 ++-- src/main/java/com/easypost/model/Error.java | 35 ++++----- .../com/easypost/model/ErrorDeserializer.java | 78 +++++++++++++++---- .../model/FieldErrorOrStringList.java | 16 ++++ .../java/com/easypost/CarrierAccountTest.java | 4 +- src/test/java/com/easypost/ErrorTest.java | 8 +- 6 files changed, 107 insertions(+), 50 deletions(-) diff --git a/src/main/java/com/easypost/model/AddressVerificationDeserializer.java b/src/main/java/com/easypost/model/AddressVerificationDeserializer.java index 719918297..21bc9392a 100644 --- a/src/main/java/com/easypost/model/AddressVerificationDeserializer.java +++ b/src/main/java/com/easypost/model/AddressVerificationDeserializer.java @@ -53,15 +53,15 @@ public AddressVerification deserialize(final JsonElement json, final Type typeOf error.setMessage(message.getAsString()); } - JsonElement field = errorAsJsonObject.get("field"); - if (field != null) { - error.setField(field.getAsString()); - } + // JsonElement field = errorAsJsonObject.get("field"); + // if (field != null) { + // error.setField(field.getAsString()); + // } - JsonElement suggestion = errorAsJsonObject.get("suggestion"); - if (suggestion != null && !suggestion.isJsonNull()) { - error.setSuggestion(suggestion.getAsString()); - } + // JsonElement suggestion = errorAsJsonObject.get("suggestion"); + // if (suggestion != null && !suggestion.isJsonNull()) { + // error.setSuggestion(suggestion.getAsString()); + // } errors.add(error); } diff --git a/src/main/java/com/easypost/model/Error.java b/src/main/java/com/easypost/model/Error.java index 963c8787e..b5264e6e2 100644 --- a/src/main/java/com/easypost/model/Error.java +++ b/src/main/java/com/easypost/model/Error.java @@ -34,25 +34,20 @@ void setCode(final String code) { * * @param errors The errors. */ - void setErrors(final FieldErrorOrStringList errors) { - this.errors = errors; - } - - /** - * Set the errors of this error object from a list of FieldError objects. - * - * @param errorList The list of FieldError objects. - */ - void setErrors(final List errorList) { - this.errors = FieldErrorOrStringList.fromErrorList(errorList); - } - - /** - * Set the errors of this error object from a list of strings. - * - * @param stringList The list of strings. - */ - void setErrorsFromStringList(final List stringList) { - this.errors = FieldErrorOrStringList.fromStringList(stringList); + void setErrors(final Object errors) { + if (errors instanceof List) { + List errorList = (List) errors; + if (!errorList.isEmpty()) { + if (errorList.get(0) instanceof FieldError) { + this.errors = FieldErrorOrStringList.fromErrorList((List) errorList); + } else if (errorList.get(0) instanceof String) { + this.errors = FieldErrorOrStringList.fromStringList((List) errorList); + } + } + } else if (errors instanceof FieldErrorOrStringList) { + this.errors = (FieldErrorOrStringList) errors; + } else { + throw new IllegalArgumentException("Invalid type for errors"); + } } } diff --git a/src/main/java/com/easypost/model/ErrorDeserializer.java b/src/main/java/com/easypost/model/ErrorDeserializer.java index 67f112b1b..5471ac0f5 100644 --- a/src/main/java/com/easypost/model/ErrorDeserializer.java +++ b/src/main/java/com/easypost/model/ErrorDeserializer.java @@ -13,6 +13,7 @@ import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Map.Entry; +import java.util.List; public final class ErrorDeserializer implements JsonDeserializer { /** @@ -49,31 +50,74 @@ private void traverseJsonElement(JsonElement element, ArrayList messages */ @Override public Error deserialize(final JsonElement json, final Type typeOfT, - final JsonDeserializationContext context) throws JsonParseException { + final JsonDeserializationContext context) throws JsonParseException { JsonObject jo = json.getAsJsonObject(); - JsonElement results = jo.get("error"); - Gson gson = new Gson(); - if (results == null) { - Error error = new Error(); + Error error = new Error(); + + JsonElement errorResponse = jo.get("error"); + if (errorResponse == null) { error.setMessage(Constants.ErrorMessages.API_DID_NOT_RETURN_ERROR_DETAILS); error.setCode("NO RESPONSE CODE"); return error; } + JsonObject errorData = errorResponse.getAsJsonObject(); - try { - ArrayList messages = new ArrayList<>(); - JsonElement errorMessageJson = results.getAsJsonObject().get("message"); - traverseJsonElement(errorMessageJson, messages); - JsonPrimitive value = new JsonPrimitive(String.join(", ", messages)); - results.getAsJsonObject().add("message", value); - } catch (Exception e) { - Error error = new Error(); - error.setMessage("Error deserializing JSON response"); - error.setCode("ERROR_DESERIALIZATION_ERROR"); - return error; + JsonElement code = errorData.get("code"); + if (code != null) { + error.setCode(code.getAsString()); + } + + JsonElement message = errorData.get("message"); + if (message != null) { + if (message.isJsonPrimitive()) { + error.setMessage(message.getAsString()); + } else if (message.isJsonObject() || message.isJsonArray()) { + ArrayList messagesList = new ArrayList<>(); + traverseJsonElement(message, messagesList); + error.setMessage(String.join(", ", messagesList)); + } else { + throw new JsonParseException("Invalid message format"); + } + } + + JsonElement errorsAsJson = errorData.get("errors"); +if (errorsAsJson != null) { + JsonArray errorsAsArray = errorsAsJson.getAsJsonArray(); + List errors = new ArrayList<>(); + for (JsonElement errorAsJson : errorsAsArray) { + if (errorAsJson.isJsonObject()) { + JsonObject errorAsJsonObject = errorAsJson.getAsJsonObject(); + FieldError fieldError = new FieldError(); + + JsonElement field = errorAsJsonObject.get("field"); + if (field != null) { + fieldError.setField(field.getAsString()); + } + + JsonElement fieldMessage = errorAsJsonObject.get("message"); + if (fieldMessage != null) { + fieldError.setMessage(fieldMessage.getAsString()); + } + + JsonElement suggestion = errorAsJsonObject.get("suggestion"); + if (suggestion != null && !suggestion.isJsonNull()) { + fieldError.setSuggestion(suggestion.getAsString()); + } + + errors.add(fieldError); + } else if (errorAsJson.isJsonPrimitive() && errorAsJson.getAsJsonPrimitive().isString()) { + errors.add(errorAsJson.getAsString()); + } + } + + if (!errors.isEmpty() && errors.get(0) instanceof FieldError) { + error.setErrors(FieldErrorOrStringList.fromErrorList((List) (List) errors)); + } else if (!errors.isEmpty() && errors.get(0) instanceof String) { + error.setErrors(FieldErrorOrStringList.fromStringList((List) (List) errors)); + } } - return gson.fromJson(results, Error.class); + return error; } } diff --git a/src/main/java/com/easypost/model/FieldErrorOrStringList.java b/src/main/java/com/easypost/model/FieldErrorOrStringList.java index f65bcd1a0..1815de4e8 100644 --- a/src/main/java/com/easypost/model/FieldErrorOrStringList.java +++ b/src/main/java/com/easypost/model/FieldErrorOrStringList.java @@ -50,4 +50,20 @@ public int size() { } return 0; } + + public String getMessage(int index) { + if (isErrorList()) { + return errorList.get(index).getMessage(); + } else if (isStringList()) { + return stringList.get(index); + } + throw new IndexOutOfBoundsException("Index out of bounds or list is empty"); + } + + public String getField(int index) { + if (isErrorList()) { + return errorList.get(index).getField(); + } + throw new UnsupportedOperationException("Field is not available for string list"); + } } diff --git a/src/test/java/com/easypost/CarrierAccountTest.java b/src/test/java/com/easypost/CarrierAccountTest.java index c4002a416..fedba5fef 100644 --- a/src/test/java/com/easypost/CarrierAccountTest.java +++ b/src/test/java/com/easypost/CarrierAccountTest.java @@ -109,8 +109,8 @@ public void testCreateWithCustomWorkflow() throws EasyPostException { // We're sending bad data to the API, so we expect an error assertEquals(422, e.getStatusCode()); // We expect one of the sub-errors to be regarding a missing field - assertTrue(e.getErrors().stream().anyMatch(error -> error.getField().equals("account_number") && - error.getMessage().equals("must be present and a string"))); + // assertTrue(e.getErrors().stream().anyMatch(error -> error.getField().equals("account_number") && + // error.getMessage().equals("must be present and a string"))); } } diff --git a/src/test/java/com/easypost/ErrorTest.java b/src/test/java/com/easypost/ErrorTest.java index 7b9da854a..a30ca1bfd 100644 --- a/src/test/java/com/easypost/ErrorTest.java +++ b/src/test/java/com/easypost/ErrorTest.java @@ -20,6 +20,8 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import com.easypost.model.FieldError; + import java.util.HashMap; import java.util.Map; @@ -54,8 +56,8 @@ public void testError() throws EasyPostException { assertEquals(422, exception.getStatusCode()); assertEquals("PARAMETER.REQUIRED", exception.getCode()); assertEquals("Missing required parameter.", exception.getMessage()); - assertEquals("cannot be blank", exception.getErrors().get(0).getMessage()); - assertEquals("shipment", exception.getErrors().get(0).getField()); + assertEquals("cannot be blank", exception.getErrors().getMessage(0)); + assertEquals("shipment", exception.getErrors().getField(0)); } /** @@ -71,7 +73,7 @@ public void testErrorAlternativeFormat() throws EasyPostException { HashMap claimData = Fixtures.basicClaim(); claimData.put("tracking_code", "123"); // Intentionally pass a bad tracking code - APIException exception = assertThrows(InvalidRequestError.class, () -> vcr.client.claim.create(claimData)); + APIException exception = assertThrows(NotFoundError.class, () -> vcr.client.claim.create(claimData)); assertEquals(404, exception.getStatusCode()); assertEquals("NOT_FOUND", exception.getCode()); From d93e46a75fec50fb0acc646c0616dc8cee172485 Mon Sep 17 00:00:00 2001 From: Justintime50 <39606064+Justintime50@users.noreply.github.com> Date: Wed, 26 Feb 2025 10:58:22 -0700 Subject: [PATCH 3/7] chore: replace Error model with APIException --- src/main/java/com/easypost/Constants.java | 4 +- .../exception/API/BadRequestError.java | 6 +- .../exception/API/ForbiddenError.java | 6 +- .../exception/API/GatewayTimeoutError.java | 6 +- .../exception/API/InternalServerError.java | 6 +- .../exception/API/InvalidRequestError.java | 6 +- .../exception/API/MethodNotAllowedError.java | 6 +- .../easypost/exception/API/NotFoundError.java | 6 +- .../easypost/exception/API/PaymentError.java | 6 +- .../exception/API/RateLimitError.java | 6 +- .../easypost/exception/API/RedirectError.java | 6 +- .../API/ServiceUnavailableError.java | 6 +- .../easypost/exception/API/TimeoutError.java | 6 +- .../exception/API/UnauthorizedError.java | 6 +- .../exception/API/UnknownApiError.java | 6 +- .../com/easypost/exception/APIException.java | 25 +++++--- .../java/com/easypost/http/Requestor.java | 32 +++++----- .../easypost/model/AddressVerification.java | 4 +- .../AddressVerificationDeserializer.java | 20 +++---- .../model/AddressVerificationFieldError.java | 48 +++++++++++++++ .../com/easypost/model/BetaPaymentRefund.java | 2 +- src/main/java/com/easypost/model/Error.java | 53 ----------------- .../com/easypost/model/ErrorDeserializer.java | 59 ++++++++++--------- .../java/com/easypost/model/FieldError.java | 1 - .../easypost/model/FieldErrorOrString.java | 35 +++++++++++ .../model/FieldErrorOrStringList.java | 26 ++------ src/test/java/com/easypost/ErrorTest.java | 4 +- 27 files changed, 211 insertions(+), 186 deletions(-) create mode 100644 src/main/java/com/easypost/model/AddressVerificationFieldError.java delete mode 100644 src/main/java/com/easypost/model/Error.java create mode 100644 src/main/java/com/easypost/model/FieldErrorOrString.java diff --git a/src/main/java/com/easypost/Constants.java b/src/main/java/com/easypost/Constants.java index c470d63b7..c36f743b5 100644 --- a/src/main/java/com/easypost/Constants.java +++ b/src/main/java/com/easypost/Constants.java @@ -1,9 +1,9 @@ package com.easypost; +import com.easypost.exception.APIException; import com.easypost.http.HashMapSerializer; import com.easypost.model.AddressVerification; import com.easypost.model.AddressVerificationDeserializer; -import com.easypost.model.Error; import com.easypost.model.ErrorDeserializer; import com.easypost.model.SmartrateCollection; import com.easypost.model.SmartrateCollectionDeserializer; @@ -80,7 +80,7 @@ public abstract static class Http { .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) .registerTypeAdapter(HashMap.class, new HashMapSerializer()) .registerTypeAdapter(SmartrateCollection.class, new SmartrateCollectionDeserializer()) - .registerTypeAdapter(Error.class, new ErrorDeserializer()) + .registerTypeAdapter(APIException.class, new ErrorDeserializer()) .registerTypeAdapter(AddressVerification.class, new AddressVerificationDeserializer()) .registerTypeAdapter(StatelessRate[].class, new StatelessRateDeserializer()) .registerTypeAdapter(Webhook[].class, new WebhookDeserializer()).create(); diff --git a/src/main/java/com/easypost/exception/API/BadRequestError.java b/src/main/java/com/easypost/exception/API/BadRequestError.java index c13cad97c..5785f1781 100644 --- a/src/main/java/com/easypost/exception/API/BadRequestError.java +++ b/src/main/java/com/easypost/exception/API/BadRequestError.java @@ -9,10 +9,10 @@ public class BadRequestError extends APIException { * * @param message the exception message * @param code the exception code - * @param statusCode the exception status code * @param errors the errors array + * @param statusCode the exception status code */ - public BadRequestError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { - super(message, code, statusCode, errors); + public BadRequestError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/ForbiddenError.java b/src/main/java/com/easypost/exception/API/ForbiddenError.java index d6f631f37..672c4f040 100644 --- a/src/main/java/com/easypost/exception/API/ForbiddenError.java +++ b/src/main/java/com/easypost/exception/API/ForbiddenError.java @@ -9,10 +9,10 @@ public class ForbiddenError extends APIException { * * @param message the exception message * @param code the exception code - * @param statusCode the exception status code * @param errors the errors array + * @param statusCode the exception status code */ - public ForbiddenError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { - super(message, code, statusCode, errors); + public ForbiddenError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/GatewayTimeoutError.java b/src/main/java/com/easypost/exception/API/GatewayTimeoutError.java index b9ad38b9a..210b669ca 100644 --- a/src/main/java/com/easypost/exception/API/GatewayTimeoutError.java +++ b/src/main/java/com/easypost/exception/API/GatewayTimeoutError.java @@ -9,10 +9,10 @@ public class GatewayTimeoutError extends APIException { * * @param message the exception message * @param code the exception code - * @param statusCode the exception status code * @param errors the errors array + * @param statusCode the exception status code */ - public GatewayTimeoutError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { - super(message, code, statusCode, errors); + public GatewayTimeoutError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/InternalServerError.java b/src/main/java/com/easypost/exception/API/InternalServerError.java index 8c2ae88c5..9f014918d 100644 --- a/src/main/java/com/easypost/exception/API/InternalServerError.java +++ b/src/main/java/com/easypost/exception/API/InternalServerError.java @@ -9,10 +9,10 @@ public class InternalServerError extends APIException { * * @param message the exception message * @param code the exception code - * @param statusCode the exception status code * @param errors the errors array + * @param statusCode the exception status code */ - public InternalServerError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { - super(message, code, statusCode, errors); + public InternalServerError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/InvalidRequestError.java b/src/main/java/com/easypost/exception/API/InvalidRequestError.java index 4fd4bae67..d2c145f2e 100644 --- a/src/main/java/com/easypost/exception/API/InvalidRequestError.java +++ b/src/main/java/com/easypost/exception/API/InvalidRequestError.java @@ -9,10 +9,10 @@ public class InvalidRequestError extends APIException { * * @param message the exception message * @param code the exception code - * @param statusCode the exception status code * @param errors the errors array + * @param statusCode the exception status code */ - public InvalidRequestError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { - super(message, code, statusCode, errors); + public InvalidRequestError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/MethodNotAllowedError.java b/src/main/java/com/easypost/exception/API/MethodNotAllowedError.java index 6adce0935..169e0f655 100644 --- a/src/main/java/com/easypost/exception/API/MethodNotAllowedError.java +++ b/src/main/java/com/easypost/exception/API/MethodNotAllowedError.java @@ -9,10 +9,10 @@ public class MethodNotAllowedError extends APIException { * * @param message the exception message * @param code the exception code - * @param statusCode the exception status code * @param errors the errors array + * @param statusCode the exception status code */ - public MethodNotAllowedError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { - super(message, code, statusCode, errors); + public MethodNotAllowedError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/NotFoundError.java b/src/main/java/com/easypost/exception/API/NotFoundError.java index b57007c38..6d1eae0b1 100644 --- a/src/main/java/com/easypost/exception/API/NotFoundError.java +++ b/src/main/java/com/easypost/exception/API/NotFoundError.java @@ -9,10 +9,10 @@ public class NotFoundError extends APIException { * * @param message the exception message * @param code the exception code - * @param statusCode the exception status code * @param errors the errors array + * @param statusCode the exception status code */ - public NotFoundError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { - super(message, code, statusCode, errors); + public NotFoundError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/PaymentError.java b/src/main/java/com/easypost/exception/API/PaymentError.java index e1299b3c6..4a11d9ef3 100644 --- a/src/main/java/com/easypost/exception/API/PaymentError.java +++ b/src/main/java/com/easypost/exception/API/PaymentError.java @@ -9,10 +9,10 @@ public class PaymentError extends APIException { * * @param message the exception message * @param code the exception code - * @param statusCode the exception status code * @param errors the errors array + * @param statusCode the exception status code */ - public PaymentError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { - super(message, code, statusCode, errors); + public PaymentError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/RateLimitError.java b/src/main/java/com/easypost/exception/API/RateLimitError.java index fcb961a74..0d47add36 100644 --- a/src/main/java/com/easypost/exception/API/RateLimitError.java +++ b/src/main/java/com/easypost/exception/API/RateLimitError.java @@ -9,10 +9,10 @@ public class RateLimitError extends APIException { * * @param message the exception message * @param code the exception code - * @param statusCode the exception status code * @param errors the errors array + * @param statusCode the exception status code */ - public RateLimitError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { - super(message, code, statusCode, errors); + public RateLimitError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/RedirectError.java b/src/main/java/com/easypost/exception/API/RedirectError.java index bebf74908..8ff443de2 100644 --- a/src/main/java/com/easypost/exception/API/RedirectError.java +++ b/src/main/java/com/easypost/exception/API/RedirectError.java @@ -9,10 +9,10 @@ public class RedirectError extends APIException { * * @param message the exception message * @param code the exception code - * @param statusCode the exception status code * @param errors the errors array + * @param statusCode the exception status code */ - public RedirectError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { - super(message, code, statusCode, errors); + public RedirectError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/ServiceUnavailableError.java b/src/main/java/com/easypost/exception/API/ServiceUnavailableError.java index 12524046b..20b2cc490 100644 --- a/src/main/java/com/easypost/exception/API/ServiceUnavailableError.java +++ b/src/main/java/com/easypost/exception/API/ServiceUnavailableError.java @@ -9,10 +9,10 @@ public class ServiceUnavailableError extends APIException { * * @param message the exception message * @param code the exception code - * @param statusCode the exception status code * @param errors the errors array + * @param statusCode the exception status code */ - public ServiceUnavailableError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { - super(message, code, statusCode, errors); + public ServiceUnavailableError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/TimeoutError.java b/src/main/java/com/easypost/exception/API/TimeoutError.java index 517644bcf..569d840d3 100644 --- a/src/main/java/com/easypost/exception/API/TimeoutError.java +++ b/src/main/java/com/easypost/exception/API/TimeoutError.java @@ -9,10 +9,10 @@ public class TimeoutError extends APIException { * * @param message the exception message * @param code the exception code - * @param statusCode the exception status code * @param errors the errors array + * @param statusCode the exception status code */ - public TimeoutError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { - super(message, code, statusCode, errors); + public TimeoutError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/UnauthorizedError.java b/src/main/java/com/easypost/exception/API/UnauthorizedError.java index 7719082e3..6edaf7f3a 100644 --- a/src/main/java/com/easypost/exception/API/UnauthorizedError.java +++ b/src/main/java/com/easypost/exception/API/UnauthorizedError.java @@ -9,10 +9,10 @@ public class UnauthorizedError extends APIException { * * @param message the exception message * @param code the exception code - * @param statusCode the exception status code * @param errors the errors array + * @param statusCode the exception status code */ - public UnauthorizedError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { - super(message, code, statusCode, errors); + public UnauthorizedError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/UnknownApiError.java b/src/main/java/com/easypost/exception/API/UnknownApiError.java index d4867b4b1..8d5783ad4 100644 --- a/src/main/java/com/easypost/exception/API/UnknownApiError.java +++ b/src/main/java/com/easypost/exception/API/UnknownApiError.java @@ -9,10 +9,10 @@ public class UnknownApiError extends APIException { * * @param message the exception message * @param code the exception code - * @param statusCode the exception status code * @param errors the errors array + * @param statusCode the exception status code */ - public UnknownApiError(final String message, final String code, final int statusCode, FieldErrorOrStringList errors) { - super(message, code, statusCode, errors); + public UnknownApiError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/APIException.java b/src/main/java/com/easypost/exception/APIException.java index 30befd359..9640e1173 100644 --- a/src/main/java/com/easypost/exception/APIException.java +++ b/src/main/java/com/easypost/exception/APIException.java @@ -1,7 +1,6 @@ package com.easypost.exception; import com.easypost.model.FieldErrorOrStringList; -import com.easypost.model.Error; public class APIException extends EasyPostException { private static final long serialVersionUID = 1L; @@ -34,11 +33,10 @@ public APIException(final String message, final Throwable ex) { * * @param message the exception message * @param code the exception code - * @param statusCode the exception status code * @param errors the errors array */ - public APIException(final String message, final String code, final int statusCode, final FieldErrorOrStringList errors) { - this(message, code, statusCode, errors, null); + public APIException(final String message, final String code, final FieldErrorOrStringList errors) { + this(message, code, errors, null); } /** @@ -46,17 +44,28 @@ public APIException(final String message, final String code, final int statusCod * * @param message the exception message * @param code the exception code + * @param errors the errors array * @param statusCode the exception status code + */ + public APIException(final String message, final String code, final FieldErrorOrStringList errors, final Integer statusCode) { + this(message, code, errors, statusCode, null); + } + + /** + * APIException constructor. + * + * @param message the exception message + * @param code the exception code * @param errors the errors array + * @param statusCode the exception status code * @param ex the exception cause */ - public APIException(final String message, final String code, final Integer statusCode, - final FieldErrorOrStringList errors, final Throwable ex) { + public APIException(final String message, final String code, final FieldErrorOrStringList errors, final Integer statusCode, final Throwable ex) { super(message); - this.code = code; - this.statusCode = statusCode; this.message = message; + this.code = code; this.errors = errors; + this.statusCode = statusCode; } /** diff --git a/src/main/java/com/easypost/http/Requestor.java b/src/main/java/com/easypost/http/Requestor.java index bf8af9e7e..7a4cfc16f 100644 --- a/src/main/java/com/easypost/http/Requestor.java +++ b/src/main/java/com/easypost/http/Requestor.java @@ -2,6 +2,7 @@ import com.easypost.Constants; import com.easypost.EasyPost; +import com.easypost.exception.APIException; import com.easypost.exception.API.BadRequestError; import com.easypost.exception.API.EncodingError; import com.easypost.exception.API.ForbiddenError; @@ -23,7 +24,6 @@ import com.easypost.hooks.RequestHookResponses; import com.easypost.hooks.ResponseHookResponses; import com.easypost.model.EasyPostResource; -import com.easypost.model.Error; import com.easypost.model.FieldErrorOrStringList; import com.easypost.service.EasyPostClient; import com.google.gson.JsonElement; @@ -643,42 +643,42 @@ protected static void handleAPIError(String rBody, final int rCode) if (rBody == null || rBody.length() == 0) { rBody = "{}"; } - Error error = Constants.Http.GSON.fromJson(rBody, Error.class); + APIException error = Constants.Http.GSON.fromJson(rBody, APIException.class); String errorMessage = error.getMessage(); String errorCode = error.getCode(); FieldErrorOrStringList errors = error.getErrors(); if (rCode >= Constants.ErrorCodes.REDIRECT_CODE_BEGIN && rCode <= Constants.ErrorCodes.REDIRECT_CODE_END) { - throw new RedirectError(errorMessage, errorCode, rCode, errors); + throw new RedirectError(errorMessage, errorCode, errors, rCode); } switch (rCode) { case Constants.ErrorCodes.UNAUTHORIZED_ERROR: - throw new UnauthorizedError(errorMessage, errorCode, rCode, errors); + throw new UnauthorizedError(errorMessage, errorCode, errors, rCode); case Constants.ErrorCodes.FORBIDDEN_ERROR: - throw new ForbiddenError(errorMessage, errorCode, rCode, errors); + throw new ForbiddenError(errorMessage, errorCode, errors, rCode); case Constants.ErrorCodes.PAYMENT_ERROR: - throw new PaymentError(errorMessage, errorCode, rCode, errors); + throw new PaymentError(errorMessage, errorCode, errors, rCode); case Constants.ErrorCodes.NOT_FOUND_ERROR: - throw new NotFoundError(errorMessage, errorCode, rCode, errors); + throw new NotFoundError(errorMessage, errorCode, errors, rCode); case Constants.ErrorCodes.METHOD_NOT_ALLOWED_ERROR: - throw new MethodNotAllowedError(errorMessage, errorCode, rCode, errors); + throw new MethodNotAllowedError(errorMessage, errorCode, errors, rCode); case Constants.ErrorCodes.TIMEOUT_ERROR: - throw new TimeoutError(errorMessage, errorCode, rCode, errors); + throw new TimeoutError(errorMessage, errorCode, errors, rCode); case Constants.ErrorCodes.BAD_REQUEST_ERROR: - throw new BadRequestError(errorMessage, errorCode, rCode, errors); + throw new BadRequestError(errorMessage, errorCode, errors, rCode); case Constants.ErrorCodes.INVALID_REQUEST_ERROR: - throw new InvalidRequestError(errorMessage, errorCode, rCode, errors); + throw new InvalidRequestError(errorMessage, errorCode, errors, rCode); case Constants.ErrorCodes.RATE_LIMIT_ERROR: - throw new RateLimitError(errorMessage, errorCode, rCode, errors); + throw new RateLimitError(errorMessage, errorCode, errors, rCode); case Constants.ErrorCodes.INTERNAL_SERVER_ERROR: - throw new InternalServerError(errorMessage, errorCode, rCode, errors); + throw new InternalServerError(errorMessage, errorCode, errors, rCode); case Constants.ErrorCodes.SERVICE_UNAVAILABLE_ERROR: - throw new ServiceUnavailableError(errorMessage, errorCode, rCode, errors); + throw new ServiceUnavailableError(errorMessage, errorCode, errors, rCode); case Constants.ErrorCodes.GATEWAY_TIMEOUT_ERROR: - throw new GatewayTimeoutError(errorMessage, errorCode, rCode, errors); + throw new GatewayTimeoutError(errorMessage, errorCode, errors, rCode); default: - throw new UnknownApiError(errorMessage, errorCode, rCode, errors); + throw new UnknownApiError(errorMessage, errorCode, errors, rCode); } } diff --git a/src/main/java/com/easypost/model/AddressVerification.java b/src/main/java/com/easypost/model/AddressVerification.java index 5e8dc7e3b..4853b3d82 100644 --- a/src/main/java/com/easypost/model/AddressVerification.java +++ b/src/main/java/com/easypost/model/AddressVerification.java @@ -6,7 +6,7 @@ @Getter public final class AddressVerification { private Boolean success; - private List errors; + private List errors; private AddressDetail details; /** @@ -23,7 +23,7 @@ void setSuccess(final boolean success) { * * @param errors The errors. */ - void setErrors(final List errors) { + void setErrors(final List errors) { this.errors = errors; } diff --git a/src/main/java/com/easypost/model/AddressVerificationDeserializer.java b/src/main/java/com/easypost/model/AddressVerificationDeserializer.java index 21bc9392a..1523fe4c8 100644 --- a/src/main/java/com/easypost/model/AddressVerificationDeserializer.java +++ b/src/main/java/com/easypost/model/AddressVerificationDeserializer.java @@ -37,11 +37,11 @@ public AddressVerification deserialize(final JsonElement json, final Type typeOf if (errorsAsJson != null) { JsonArray errorsAsArray = errorsAsJson.getAsJsonArray(); - ArrayList errors = new ArrayList<>(); + ArrayList errors = new ArrayList<>(); for (JsonElement errorAsJson : errorsAsArray) { JsonObject errorAsJsonObject = errorAsJson.getAsJsonObject(); - Error error = new Error(); + AddressVerificationFieldError error = new AddressVerificationFieldError(); JsonElement code = errorAsJsonObject.get("code"); if (code != null) { @@ -53,15 +53,15 @@ public AddressVerification deserialize(final JsonElement json, final Type typeOf error.setMessage(message.getAsString()); } - // JsonElement field = errorAsJsonObject.get("field"); - // if (field != null) { - // error.setField(field.getAsString()); - // } + JsonElement field = errorAsJsonObject.get("field"); + if (field != null) { + error.setField(field.getAsString()); + } - // JsonElement suggestion = errorAsJsonObject.get("suggestion"); - // if (suggestion != null && !suggestion.isJsonNull()) { - // error.setSuggestion(suggestion.getAsString()); - // } + JsonElement suggestion = errorAsJsonObject.get("suggestion"); + if (suggestion != null && !suggestion.isJsonNull()) { + error.setSuggestion(suggestion.getAsString()); + } errors.add(error); } diff --git a/src/main/java/com/easypost/model/AddressVerificationFieldError.java b/src/main/java/com/easypost/model/AddressVerificationFieldError.java new file mode 100644 index 000000000..805b3b80c --- /dev/null +++ b/src/main/java/com/easypost/model/AddressVerificationFieldError.java @@ -0,0 +1,48 @@ +package com.easypost.model; + +import java.util.List; +import lombok.Getter; + +@Getter +public final class AddressVerificationFieldError { + private String code; + private String field; + private String message; + private String suggestion; + + /** + * Set the code of this error object. + * + * @param code The code. + */ + void setCode(final String code) { + this.code = code; + } + + /** + * Set the field of this error object. + * + * @param field The field. + */ + void setField(final String field) { + this.field = field; + } + + /** + * Set the message of this error object. + * + * @param message The error message. + */ + void setMessage(final String message) { + this.message = message; + } + + /** + * Set the suggestion of this error object. + * + * @param suggestion The suggestion. + */ + void setSuggestion(final String suggestion) { + this.suggestion = suggestion; + } +} diff --git a/src/main/java/com/easypost/model/BetaPaymentRefund.java b/src/main/java/com/easypost/model/BetaPaymentRefund.java index 6970b5529..3dc22709f 100644 --- a/src/main/java/com/easypost/model/BetaPaymentRefund.java +++ b/src/main/java/com/easypost/model/BetaPaymentRefund.java @@ -6,7 +6,7 @@ @Getter public class BetaPaymentRefund extends EasyPostResource{ private int refundedAmount; - private List errors; + private List errors; private List refundedPaymentLogs; private String paymentLogId; private String refundedAmountCurrencys; diff --git a/src/main/java/com/easypost/model/Error.java b/src/main/java/com/easypost/model/Error.java deleted file mode 100644 index b5264e6e2..000000000 --- a/src/main/java/com/easypost/model/Error.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.easypost.model; - -import lombok.Getter; - -import java.util.List; - -@Getter -@SuppressWarnings("JavaLangClash") -public final class Error { - private String message; - private String code; - private FieldErrorOrStringList errors; - - /** - * Set the message of this error object. - * - * @param message The error message. - */ - void setMessage(final String message) { - this.message = message; - } - - /** - * Set the code of this error object. - * - * @param code The error code. - */ - void setCode(final String code) { - this.code = code; - } - - /** - * Set the errors of this error object. - * - * @param errors The errors. - */ - void setErrors(final Object errors) { - if (errors instanceof List) { - List errorList = (List) errors; - if (!errorList.isEmpty()) { - if (errorList.get(0) instanceof FieldError) { - this.errors = FieldErrorOrStringList.fromErrorList((List) errorList); - } else if (errorList.get(0) instanceof String) { - this.errors = FieldErrorOrStringList.fromStringList((List) errorList); - } - } - } else if (errors instanceof FieldErrorOrStringList) { - this.errors = (FieldErrorOrStringList) errors; - } else { - throw new IllegalArgumentException("Invalid type for errors"); - } - } -} diff --git a/src/main/java/com/easypost/model/ErrorDeserializer.java b/src/main/java/com/easypost/model/ErrorDeserializer.java index 5471ac0f5..fbf90ec9b 100644 --- a/src/main/java/com/easypost/model/ErrorDeserializer.java +++ b/src/main/java/com/easypost/model/ErrorDeserializer.java @@ -1,6 +1,7 @@ package com.easypost.model; import com.easypost.Constants; +import com.easypost.exception.APIException; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; @@ -15,7 +16,7 @@ import java.util.Map.Entry; import java.util.List; -public final class ErrorDeserializer implements JsonDeserializer { +public final class ErrorDeserializer implements JsonDeserializer { /** * Recursively traverse an error JSON element and its sub-element(s), and extracts all * error string values found into the specified string list. @@ -40,51 +41,53 @@ private void traverseJsonElement(JsonElement element, ArrayList messages } /** - * Deserialize an Error from a JSON object. + * Deserialize an APIException from a JSON object. * * @param json JSON object to deserialize. * @param typeOfT Type of the object to deserialize. * @param context Deserialization context. - * @return Deserialized Error object. + * @return Deserialized APIException object. * @throws JsonParseException if the JSON object is not a valid SmartrateCollection. */ @Override - public Error deserialize(final JsonElement json, final Type typeOfT, + public APIException deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException { JsonObject jo = json.getAsJsonObject(); - Error error = new Error(); + String message = null; + String code = null; + FieldErrorOrStringList errors = null; JsonElement errorResponse = jo.get("error"); if (errorResponse == null) { - error.setMessage(Constants.ErrorMessages.API_DID_NOT_RETURN_ERROR_DETAILS); - error.setCode("NO RESPONSE CODE"); - return error; + message = Constants.ErrorMessages.API_DID_NOT_RETURN_ERROR_DETAILS; + code = "NO RESPONSE CODE"; + return new APIException(message, code, null); } JsonObject errorData = errorResponse.getAsJsonObject(); - JsonElement code = errorData.get("code"); - if (code != null) { - error.setCode(code.getAsString()); + JsonElement codeElement = errorData.get("code"); + if (codeElement != null) { + code = codeElement.getAsString(); } - JsonElement message = errorData.get("message"); - if (message != null) { - if (message.isJsonPrimitive()) { - error.setMessage(message.getAsString()); - } else if (message.isJsonObject() || message.isJsonArray()) { + JsonElement messageElement = errorData.get("message"); + if (messageElement != null) { + if (messageElement.isJsonPrimitive()) { + message = messageElement.getAsString(); + } else if (messageElement.isJsonObject() || messageElement.isJsonArray()) { ArrayList messagesList = new ArrayList<>(); - traverseJsonElement(message, messagesList); - error.setMessage(String.join(", ", messagesList)); + traverseJsonElement(messageElement, messagesList); + message = String.join(", ", messagesList); } else { throw new JsonParseException("Invalid message format"); } } JsonElement errorsAsJson = errorData.get("errors"); -if (errorsAsJson != null) { + if (errorsAsJson != null) { JsonArray errorsAsArray = errorsAsJson.getAsJsonArray(); - List errors = new ArrayList<>(); + List errorList = new ArrayList<>(); for (JsonElement errorAsJson : errorsAsArray) { if (errorAsJson.isJsonObject()) { JsonObject errorAsJsonObject = errorAsJson.getAsJsonObject(); @@ -105,19 +108,19 @@ public Error deserialize(final JsonElement json, final Type typeOfT, fieldError.setSuggestion(suggestion.getAsString()); } - errors.add(fieldError); - } else if (errorAsJson.isJsonPrimitive() && errorAsJson.getAsJsonPrimitive().isString()) { - errors.add(errorAsJson.getAsString()); + errorList.add(fieldError); + } else { + errorList.add(errorAsJson.getAsString()); } } - if (!errors.isEmpty() && errors.get(0) instanceof FieldError) { - error.setErrors(FieldErrorOrStringList.fromErrorList((List) (List) errors)); - } else if (!errors.isEmpty() && errors.get(0) instanceof String) { - error.setErrors(FieldErrorOrStringList.fromStringList((List) (List) errors)); + if (!errorList.isEmpty() && errorList.get(0) instanceof FieldError) { + errors = FieldErrorOrStringList.fromErrorList((List) (List) errorList); + } else if (!errorList.isEmpty() && errorList.get(0) instanceof String) { + errors = FieldErrorOrStringList.fromStringList((List) (List) errorList); } } - return error; + return new APIException(message, code, errors); } } diff --git a/src/main/java/com/easypost/model/FieldError.java b/src/main/java/com/easypost/model/FieldError.java index 6daee0c93..9d8b5cbdd 100644 --- a/src/main/java/com/easypost/model/FieldError.java +++ b/src/main/java/com/easypost/model/FieldError.java @@ -4,7 +4,6 @@ import lombok.Getter; @Getter -@SuppressWarnings("JavaLangClash") public final class FieldError { private String field; private String message; diff --git a/src/main/java/com/easypost/model/FieldErrorOrString.java b/src/main/java/com/easypost/model/FieldErrorOrString.java new file mode 100644 index 000000000..7f5776b57 --- /dev/null +++ b/src/main/java/com/easypost/model/FieldErrorOrString.java @@ -0,0 +1,35 @@ +package com.easypost.model; + +import lombok.Getter; + +@Getter +public final class FieldErrorOrString { + private final FieldError fieldError; + private final String stringError; + + public FieldErrorOrString(FieldError fieldError) { + this.fieldError = fieldError; + this.stringError = null; + } + + public FieldErrorOrString(String stringError) { + this.fieldError = null; + this.stringError = stringError; + } + + public String getMessage() { + if (fieldError != null) { + return fieldError.getMessage(); + } else { + return stringError; + } + } + + public String getField() { + if (fieldError != null) { + return fieldError.getField(); + } else { + throw new UnsupportedOperationException("Field is not available for string error"); + } + } +} diff --git a/src/main/java/com/easypost/model/FieldErrorOrStringList.java b/src/main/java/com/easypost/model/FieldErrorOrStringList.java index 1815de4e8..a8d36f50b 100644 --- a/src/main/java/com/easypost/model/FieldErrorOrStringList.java +++ b/src/main/java/com/easypost/model/FieldErrorOrStringList.java @@ -6,7 +6,7 @@ import java.util.List; @Getter -public class FieldErrorOrStringList extends AbstractList { +public final class FieldErrorOrStringList extends AbstractList { private final List errorList; private final List stringList; @@ -30,13 +30,13 @@ public boolean isErrorList() { public boolean isStringList() { return stringList != null; } - + @Override - public Object get(int index) { + public FieldErrorOrString get(int index) { if (isErrorList()) { - return errorList.get(index); + return new FieldErrorOrString(errorList.get(index)); } else if (isStringList()) { - return stringList.get(index); + return new FieldErrorOrString(stringList.get(index)); } throw new IndexOutOfBoundsException("Index out of bounds or list is empty"); } @@ -50,20 +50,4 @@ public int size() { } return 0; } - - public String getMessage(int index) { - if (isErrorList()) { - return errorList.get(index).getMessage(); - } else if (isStringList()) { - return stringList.get(index); - } - throw new IndexOutOfBoundsException("Index out of bounds or list is empty"); - } - - public String getField(int index) { - if (isErrorList()) { - return errorList.get(index).getField(); - } - throw new UnsupportedOperationException("Field is not available for string list"); - } } diff --git a/src/test/java/com/easypost/ErrorTest.java b/src/test/java/com/easypost/ErrorTest.java index a30ca1bfd..512e467bd 100644 --- a/src/test/java/com/easypost/ErrorTest.java +++ b/src/test/java/com/easypost/ErrorTest.java @@ -56,8 +56,8 @@ public void testError() throws EasyPostException { assertEquals(422, exception.getStatusCode()); assertEquals("PARAMETER.REQUIRED", exception.getCode()); assertEquals("Missing required parameter.", exception.getMessage()); - assertEquals("cannot be blank", exception.getErrors().getMessage(0)); - assertEquals("shipment", exception.getErrors().getField(0)); + // assertEquals("cannot be blank", exception.getErrors().get(0)); + // assertEquals("shipment", exception.getErrors().get(0).getField()); } /** From 5f4cb0bd0e2a07947457c8c2080b14818ad7c7e7 Mon Sep 17 00:00:00 2001 From: Justintime50 <39606064+Justintime50@users.noreply.github.com> Date: Wed, 26 Feb 2025 13:49:36 -0700 Subject: [PATCH 4/7] fix: deserializer --- .../exception/API/BadRequestError.java | 5 +- .../exception/API/ForbiddenError.java | 5 +- .../exception/API/GatewayTimeoutError.java | 5 +- .../exception/API/InternalServerError.java | 5 +- .../exception/API/InvalidRequestError.java | 5 +- .../exception/API/MethodNotAllowedError.java | 5 +- .../easypost/exception/API/NotFoundError.java | 5 +- .../easypost/exception/API/PaymentError.java | 5 +- .../exception/API/RateLimitError.java | 5 +- .../easypost/exception/API/RedirectError.java | 5 +- .../API/ServiceUnavailableError.java | 5 +- .../easypost/exception/API/TimeoutError.java | 5 +- .../exception/API/UnauthorizedError.java | 5 +- .../exception/API/UnknownApiError.java | 5 +- .../com/easypost/exception/APIException.java | 16 +++--- .../java/com/easypost/http/Requestor.java | 3 +- .../com/easypost/model/ErrorDeserializer.java | 16 ++---- .../easypost/model/FieldErrorOrString.java | 35 ------------ .../model/FieldErrorOrStringList.java | 53 ------------------- src/test/java/com/easypost/ErrorTest.java | 6 ++- 20 files changed, 60 insertions(+), 139 deletions(-) delete mode 100644 src/main/java/com/easypost/model/FieldErrorOrString.java delete mode 100644 src/main/java/com/easypost/model/FieldErrorOrStringList.java diff --git a/src/main/java/com/easypost/exception/API/BadRequestError.java b/src/main/java/com/easypost/exception/API/BadRequestError.java index 5785f1781..becea3047 100644 --- a/src/main/java/com/easypost/exception/API/BadRequestError.java +++ b/src/main/java/com/easypost/exception/API/BadRequestError.java @@ -1,8 +1,9 @@ package com.easypost.exception.API; -import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; +import java.util.List; + public class BadRequestError extends APIException { /** * BadRequestError constructor. @@ -12,7 +13,7 @@ public class BadRequestError extends APIException { * @param errors the errors array * @param statusCode the exception status code */ - public BadRequestError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + public BadRequestError(final String message, final String code, List errors, final int statusCode) { super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/ForbiddenError.java b/src/main/java/com/easypost/exception/API/ForbiddenError.java index 672c4f040..bb6165365 100644 --- a/src/main/java/com/easypost/exception/API/ForbiddenError.java +++ b/src/main/java/com/easypost/exception/API/ForbiddenError.java @@ -1,8 +1,9 @@ package com.easypost.exception.API; -import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; +import java.util.List; + public class ForbiddenError extends APIException { /** * ForbiddenError constructor. @@ -12,7 +13,7 @@ public class ForbiddenError extends APIException { * @param errors the errors array * @param statusCode the exception status code */ - public ForbiddenError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + public ForbiddenError(final String message, final String code, List errors, final int statusCode) { super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/GatewayTimeoutError.java b/src/main/java/com/easypost/exception/API/GatewayTimeoutError.java index 210b669ca..3592e218e 100644 --- a/src/main/java/com/easypost/exception/API/GatewayTimeoutError.java +++ b/src/main/java/com/easypost/exception/API/GatewayTimeoutError.java @@ -1,8 +1,9 @@ package com.easypost.exception.API; -import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; +import java.util.List; + public class GatewayTimeoutError extends APIException { /** * GatewayTimeoutError constructor. @@ -12,7 +13,7 @@ public class GatewayTimeoutError extends APIException { * @param errors the errors array * @param statusCode the exception status code */ - public GatewayTimeoutError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + public GatewayTimeoutError(final String message, final String code, List errors, final int statusCode) { super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/InternalServerError.java b/src/main/java/com/easypost/exception/API/InternalServerError.java index 9f014918d..a8b6e0769 100644 --- a/src/main/java/com/easypost/exception/API/InternalServerError.java +++ b/src/main/java/com/easypost/exception/API/InternalServerError.java @@ -1,8 +1,9 @@ package com.easypost.exception.API; -import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; +import java.util.List; + public class InternalServerError extends APIException { /** * InternalServerError constructor. @@ -12,7 +13,7 @@ public class InternalServerError extends APIException { * @param errors the errors array * @param statusCode the exception status code */ - public InternalServerError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + public InternalServerError(final String message, final String code, List errors, final int statusCode) { super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/InvalidRequestError.java b/src/main/java/com/easypost/exception/API/InvalidRequestError.java index d2c145f2e..69b770831 100644 --- a/src/main/java/com/easypost/exception/API/InvalidRequestError.java +++ b/src/main/java/com/easypost/exception/API/InvalidRequestError.java @@ -1,8 +1,9 @@ package com.easypost.exception.API; -import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; +import java.util.List; + public class InvalidRequestError extends APIException { /** * InvalidRequestError constructor. @@ -12,7 +13,7 @@ public class InvalidRequestError extends APIException { * @param errors the errors array * @param statusCode the exception status code */ - public InvalidRequestError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + public InvalidRequestError(final String message, final String code, List errors, final int statusCode) { super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/MethodNotAllowedError.java b/src/main/java/com/easypost/exception/API/MethodNotAllowedError.java index 169e0f655..a72b643eb 100644 --- a/src/main/java/com/easypost/exception/API/MethodNotAllowedError.java +++ b/src/main/java/com/easypost/exception/API/MethodNotAllowedError.java @@ -1,8 +1,9 @@ package com.easypost.exception.API; -import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; +import java.util.List; + public class MethodNotAllowedError extends APIException { /** * MethodNotAllowedError constructor. @@ -12,7 +13,7 @@ public class MethodNotAllowedError extends APIException { * @param errors the errors array * @param statusCode the exception status code */ - public MethodNotAllowedError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + public MethodNotAllowedError(final String message, final String code, List errors, final int statusCode) { super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/NotFoundError.java b/src/main/java/com/easypost/exception/API/NotFoundError.java index 6d1eae0b1..7722d2693 100644 --- a/src/main/java/com/easypost/exception/API/NotFoundError.java +++ b/src/main/java/com/easypost/exception/API/NotFoundError.java @@ -1,8 +1,9 @@ package com.easypost.exception.API; -import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; +import java.util.List; + public class NotFoundError extends APIException { /** * NotFoundError constructor. @@ -12,7 +13,7 @@ public class NotFoundError extends APIException { * @param errors the errors array * @param statusCode the exception status code */ - public NotFoundError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + public NotFoundError(final String message, final String code, List errors, final int statusCode) { super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/PaymentError.java b/src/main/java/com/easypost/exception/API/PaymentError.java index 4a11d9ef3..0ee85bfb0 100644 --- a/src/main/java/com/easypost/exception/API/PaymentError.java +++ b/src/main/java/com/easypost/exception/API/PaymentError.java @@ -1,8 +1,9 @@ package com.easypost.exception.API; -import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; +import java.util.List; + public class PaymentError extends APIException { /** * PaymentError constructor. @@ -12,7 +13,7 @@ public class PaymentError extends APIException { * @param errors the errors array * @param statusCode the exception status code */ - public PaymentError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + public PaymentError(final String message, final String code, List errors, final int statusCode) { super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/RateLimitError.java b/src/main/java/com/easypost/exception/API/RateLimitError.java index 0d47add36..4e3d67c6a 100644 --- a/src/main/java/com/easypost/exception/API/RateLimitError.java +++ b/src/main/java/com/easypost/exception/API/RateLimitError.java @@ -1,8 +1,9 @@ package com.easypost.exception.API; -import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; +import java.util.List; + public class RateLimitError extends APIException { /** * RateLimitError constructor. @@ -12,7 +13,7 @@ public class RateLimitError extends APIException { * @param errors the errors array * @param statusCode the exception status code */ - public RateLimitError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + public RateLimitError(final String message, final String code, List errors, final int statusCode) { super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/RedirectError.java b/src/main/java/com/easypost/exception/API/RedirectError.java index 8ff443de2..7de23bf51 100644 --- a/src/main/java/com/easypost/exception/API/RedirectError.java +++ b/src/main/java/com/easypost/exception/API/RedirectError.java @@ -1,8 +1,9 @@ package com.easypost.exception.API; -import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; +import java.util.List; + public class RedirectError extends APIException { /** * RedirectError constructor. @@ -12,7 +13,7 @@ public class RedirectError extends APIException { * @param errors the errors array * @param statusCode the exception status code */ - public RedirectError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + public RedirectError(final String message, final String code, List errors, final int statusCode) { super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/ServiceUnavailableError.java b/src/main/java/com/easypost/exception/API/ServiceUnavailableError.java index 20b2cc490..fe13a6e23 100644 --- a/src/main/java/com/easypost/exception/API/ServiceUnavailableError.java +++ b/src/main/java/com/easypost/exception/API/ServiceUnavailableError.java @@ -1,8 +1,9 @@ package com.easypost.exception.API; -import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; +import java.util.List; + public class ServiceUnavailableError extends APIException { /** * ServiceUnavailablError constructor. @@ -12,7 +13,7 @@ public class ServiceUnavailableError extends APIException { * @param errors the errors array * @param statusCode the exception status code */ - public ServiceUnavailableError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + public ServiceUnavailableError(final String message, final String code, List errors, final int statusCode) { super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/TimeoutError.java b/src/main/java/com/easypost/exception/API/TimeoutError.java index 569d840d3..239966ad5 100644 --- a/src/main/java/com/easypost/exception/API/TimeoutError.java +++ b/src/main/java/com/easypost/exception/API/TimeoutError.java @@ -1,8 +1,9 @@ package com.easypost.exception.API; -import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; +import java.util.List; + public class TimeoutError extends APIException { /** * TimeoutError constructor. @@ -12,7 +13,7 @@ public class TimeoutError extends APIException { * @param errors the errors array * @param statusCode the exception status code */ - public TimeoutError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + public TimeoutError(final String message, final String code, List errors, final int statusCode) { super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/UnauthorizedError.java b/src/main/java/com/easypost/exception/API/UnauthorizedError.java index 6edaf7f3a..9fcee9262 100644 --- a/src/main/java/com/easypost/exception/API/UnauthorizedError.java +++ b/src/main/java/com/easypost/exception/API/UnauthorizedError.java @@ -1,8 +1,9 @@ package com.easypost.exception.API; -import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; +import java.util.List; + public class UnauthorizedError extends APIException { /** * UnauthorizedError constructor. @@ -12,7 +13,7 @@ public class UnauthorizedError extends APIException { * @param errors the errors array * @param statusCode the exception status code */ - public UnauthorizedError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + public UnauthorizedError(final String message, final String code, List errors, final int statusCode) { super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/API/UnknownApiError.java b/src/main/java/com/easypost/exception/API/UnknownApiError.java index 8d5783ad4..6a1796b12 100644 --- a/src/main/java/com/easypost/exception/API/UnknownApiError.java +++ b/src/main/java/com/easypost/exception/API/UnknownApiError.java @@ -1,8 +1,9 @@ package com.easypost.exception.API; -import com.easypost.model.FieldErrorOrStringList; import com.easypost.exception.APIException; +import java.util.List; + public class UnknownApiError extends APIException { /** * UnknownApiError constructor. @@ -12,7 +13,7 @@ public class UnknownApiError extends APIException { * @param errors the errors array * @param statusCode the exception status code */ - public UnknownApiError(final String message, final String code, FieldErrorOrStringList errors, final int statusCode) { + public UnknownApiError(final String message, final String code, List errors, final int statusCode) { super(message, code, errors, statusCode); } } diff --git a/src/main/java/com/easypost/exception/APIException.java b/src/main/java/com/easypost/exception/APIException.java index 9640e1173..2956bd24f 100644 --- a/src/main/java/com/easypost/exception/APIException.java +++ b/src/main/java/com/easypost/exception/APIException.java @@ -1,13 +1,13 @@ package com.easypost.exception; -import com.easypost.model.FieldErrorOrStringList; +import java.util.List; public class APIException extends EasyPostException { private static final long serialVersionUID = 1L; private final String code; private final Integer statusCode; private final String message; - private final FieldErrorOrStringList errors; + private final List errors; /** * APIException constructor. @@ -15,7 +15,7 @@ public class APIException extends EasyPostException { * @param message the exception message */ public APIException(final String message) { - this(message, null); + this(message, null, null, null, null); } /** @@ -35,8 +35,8 @@ public APIException(final String message, final Throwable ex) { * @param code the exception code * @param errors the errors array */ - public APIException(final String message, final String code, final FieldErrorOrStringList errors) { - this(message, code, errors, null); + public APIException(final String message, final String code, final List errors) { + this(message, code, errors, null, null); } /** @@ -47,7 +47,7 @@ public APIException(final String message, final String code, final FieldErrorOrS * @param errors the errors array * @param statusCode the exception status code */ - public APIException(final String message, final String code, final FieldErrorOrStringList errors, final Integer statusCode) { + public APIException(final String message, final String code, final List errors, final Integer statusCode) { this(message, code, errors, statusCode, null); } @@ -60,7 +60,7 @@ public APIException(final String message, final String code, final FieldErrorOrS * @param statusCode the exception status code * @param ex the exception cause */ - public APIException(final String message, final String code, final FieldErrorOrStringList errors, final Integer statusCode, final Throwable ex) { + public APIException(final String message, final String code, final List errors, final Integer statusCode, final Throwable ex) { super(message); this.message = message; this.code = code; @@ -101,7 +101,7 @@ public String getMessage() { * * @return errors of the exception */ - public FieldErrorOrStringList getErrors() { + public List getErrors() { return errors; } } diff --git a/src/main/java/com/easypost/http/Requestor.java b/src/main/java/com/easypost/http/Requestor.java index 7a4cfc16f..5c3592e7f 100644 --- a/src/main/java/com/easypost/http/Requestor.java +++ b/src/main/java/com/easypost/http/Requestor.java @@ -24,7 +24,6 @@ import com.easypost.hooks.RequestHookResponses; import com.easypost.hooks.ResponseHookResponses; import com.easypost.model.EasyPostResource; -import com.easypost.model.FieldErrorOrStringList; import com.easypost.service.EasyPostClient; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -646,7 +645,7 @@ protected static void handleAPIError(String rBody, final int rCode) APIException error = Constants.Http.GSON.fromJson(rBody, APIException.class); String errorMessage = error.getMessage(); String errorCode = error.getCode(); - FieldErrorOrStringList errors = error.getErrors(); + List errors = error.getErrors(); if (rCode >= Constants.ErrorCodes.REDIRECT_CODE_BEGIN && rCode <= Constants.ErrorCodes.REDIRECT_CODE_END) { throw new RedirectError(errorMessage, errorCode, errors, rCode); diff --git a/src/main/java/com/easypost/model/ErrorDeserializer.java b/src/main/java/com/easypost/model/ErrorDeserializer.java index fbf90ec9b..dbdab3c3b 100644 --- a/src/main/java/com/easypost/model/ErrorDeserializer.java +++ b/src/main/java/com/easypost/model/ErrorDeserializer.java @@ -13,8 +13,8 @@ import java.lang.reflect.Type; import java.util.ArrayList; -import java.util.Map.Entry; import java.util.List; +import java.util.Map.Entry; public final class ErrorDeserializer implements JsonDeserializer { /** @@ -51,12 +51,12 @@ private void traverseJsonElement(JsonElement element, ArrayList messages */ @Override public APIException deserialize(final JsonElement json, final Type typeOfT, - final JsonDeserializationContext context) throws JsonParseException { + final JsonDeserializationContext context) throws JsonParseException { JsonObject jo = json.getAsJsonObject(); String message = null; String code = null; - FieldErrorOrStringList errors = null; + List errors = new ArrayList<>(); JsonElement errorResponse = jo.get("error"); if (errorResponse == null) { @@ -85,9 +85,9 @@ public APIException deserialize(final JsonElement json, final Type typeOfT, } JsonElement errorsAsJson = errorData.get("errors"); + List errorList = new ArrayList<>(); if (errorsAsJson != null) { JsonArray errorsAsArray = errorsAsJson.getAsJsonArray(); - List errorList = new ArrayList<>(); for (JsonElement errorAsJson : errorsAsArray) { if (errorAsJson.isJsonObject()) { JsonObject errorAsJsonObject = errorAsJson.getAsJsonObject(); @@ -113,14 +113,8 @@ public APIException deserialize(final JsonElement json, final Type typeOfT, errorList.add(errorAsJson.getAsString()); } } - - if (!errorList.isEmpty() && errorList.get(0) instanceof FieldError) { - errors = FieldErrorOrStringList.fromErrorList((List) (List) errorList); - } else if (!errorList.isEmpty() && errorList.get(0) instanceof String) { - errors = FieldErrorOrStringList.fromStringList((List) (List) errorList); - } } - return new APIException(message, code, errors); + return new APIException(message, code, errorList); } } diff --git a/src/main/java/com/easypost/model/FieldErrorOrString.java b/src/main/java/com/easypost/model/FieldErrorOrString.java deleted file mode 100644 index 7f5776b57..000000000 --- a/src/main/java/com/easypost/model/FieldErrorOrString.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.easypost.model; - -import lombok.Getter; - -@Getter -public final class FieldErrorOrString { - private final FieldError fieldError; - private final String stringError; - - public FieldErrorOrString(FieldError fieldError) { - this.fieldError = fieldError; - this.stringError = null; - } - - public FieldErrorOrString(String stringError) { - this.fieldError = null; - this.stringError = stringError; - } - - public String getMessage() { - if (fieldError != null) { - return fieldError.getMessage(); - } else { - return stringError; - } - } - - public String getField() { - if (fieldError != null) { - return fieldError.getField(); - } else { - throw new UnsupportedOperationException("Field is not available for string error"); - } - } -} diff --git a/src/main/java/com/easypost/model/FieldErrorOrStringList.java b/src/main/java/com/easypost/model/FieldErrorOrStringList.java deleted file mode 100644 index a8d36f50b..000000000 --- a/src/main/java/com/easypost/model/FieldErrorOrStringList.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.easypost.model; - -import lombok.Getter; - -import java.util.AbstractList; -import java.util.List; - -@Getter -public final class FieldErrorOrStringList extends AbstractList { - private final List errorList; - private final List stringList; - - private FieldErrorOrStringList(List errorList, List stringList) { - this.errorList = errorList; - this.stringList = stringList; - } - - public static FieldErrorOrStringList fromErrorList(List errorList) { - return new FieldErrorOrStringList(errorList, null); - } - - public static FieldErrorOrStringList fromStringList(List stringList) { - return new FieldErrorOrStringList(null, stringList); - } - - public boolean isErrorList() { - return errorList != null; - } - - public boolean isStringList() { - return stringList != null; - } - - @Override - public FieldErrorOrString get(int index) { - if (isErrorList()) { - return new FieldErrorOrString(errorList.get(index)); - } else if (isStringList()) { - return new FieldErrorOrString(stringList.get(index)); - } - throw new IndexOutOfBoundsException("Index out of bounds or list is empty"); - } - - @Override - public int size() { - if (isErrorList()) { - return errorList.size(); - } else if (isStringList()) { - return stringList.size(); - } - return 0; - } -} diff --git a/src/test/java/com/easypost/ErrorTest.java b/src/test/java/com/easypost/ErrorTest.java index 512e467bd..7986bcfea 100644 --- a/src/test/java/com/easypost/ErrorTest.java +++ b/src/test/java/com/easypost/ErrorTest.java @@ -17,6 +17,7 @@ import com.easypost.exception.APIException; import com.easypost.exception.EasyPostException; import com.easypost.http.Requestor; +import com.easypost.model.FieldError; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -56,8 +57,9 @@ public void testError() throws EasyPostException { assertEquals(422, exception.getStatusCode()); assertEquals("PARAMETER.REQUIRED", exception.getCode()); assertEquals("Missing required parameter.", exception.getMessage()); - // assertEquals("cannot be blank", exception.getErrors().get(0)); - // assertEquals("shipment", exception.getErrors().get(0).getField()); + FieldError fieldError = (FieldError) exception.getErrors().get(0); + assertEquals("cannot be blank", fieldError.getMessage()); + assertEquals("shipment", fieldError.getField()); } /** From 24d447b6bb907ade4fd7ca546fa4c261c28afe8a Mon Sep 17 00:00:00 2001 From: Justintime50 <39606064+Justintime50@users.noreply.github.com> Date: Wed, 26 Feb 2025 14:11:23 -0700 Subject: [PATCH 5/7] test: address verificatione errors --- src/test/java/com/easypost/AddressTest.java | 19 +++++++++++++++++-- .../java/com/easypost/CarrierAccountTest.java | 6 ++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/easypost/AddressTest.java b/src/test/java/com/easypost/AddressTest.java index ac7b483bd..b95d74b37 100644 --- a/src/test/java/com/easypost/AddressTest.java +++ b/src/test/java/com/easypost/AddressTest.java @@ -5,6 +5,8 @@ import com.easypost.exception.General.EndOfPaginationError; import com.easypost.model.Address; import com.easypost.model.AddressCollection; +import com.easypost.model.AddressDetail; +import com.easypost.model.AddressVerificationFieldError; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -88,8 +90,21 @@ public void testCreateVerify() throws EasyPostException { address = vcr.client.address.create(addressData); assertInstanceOf(Address.class, address); - assertNotNull(address.getVerifications().getDelivery()); - assertNotNull(address.getVerifications().getZip4()); + assertEquals(false, address.getVerifications().getDelivery().getSuccess()); + assertInstanceOf(AddressDetail.class, address.getVerifications().getDelivery().getDetails()); + AddressVerificationFieldError addressVerificationFieldErrorGetDelivery = address.getVerifications().getDelivery().getErrors().get(0); + assertEquals("E.ADDRESS.NOT_FOUND", addressVerificationFieldErrorGetDelivery.getCode()); + assertEquals("address", addressVerificationFieldErrorGetDelivery.getField()); + assertNull(addressVerificationFieldErrorGetDelivery.getSuggestion()); + assertEquals("Address not found", addressVerificationFieldErrorGetDelivery.getMessage()); + + assertEquals(false, address.getVerifications().getZip4().getSuccess()); + assertNull(address.getVerifications().getZip4().getDetails()); + AddressVerificationFieldError addressVerificationFieldErrorZip4 = address.getVerifications().getZip4().getErrors().get(0); + assertEquals("E.ADDRESS.NOT_FOUND", addressVerificationFieldErrorZip4.getCode()); + assertEquals("address", addressVerificationFieldErrorZip4.getField()); + assertNull(addressVerificationFieldErrorZip4.getSuggestion()); + assertEquals("Address not found", addressVerificationFieldErrorZip4.getMessage()); } /** diff --git a/src/test/java/com/easypost/CarrierAccountTest.java b/src/test/java/com/easypost/CarrierAccountTest.java index fedba5fef..24f3119eb 100644 --- a/src/test/java/com/easypost/CarrierAccountTest.java +++ b/src/test/java/com/easypost/CarrierAccountTest.java @@ -5,6 +5,7 @@ import com.easypost.http.Requestor; import com.easypost.model.CarrierAccount; import com.easypost.model.CarrierType; +import com.easypost.model.FieldError; import com.easypost.model.Pickup; import com.easypost.model.Shipment; import com.google.common.collect.ImmutableMap; @@ -109,8 +110,9 @@ public void testCreateWithCustomWorkflow() throws EasyPostException { // We're sending bad data to the API, so we expect an error assertEquals(422, e.getStatusCode()); // We expect one of the sub-errors to be regarding a missing field - // assertTrue(e.getErrors().stream().anyMatch(error -> error.getField().equals("account_number") && - // error.getMessage().equals("must be present and a string"))); + FieldError fieldError = (FieldError) e.getErrors().get(0); + assertEquals("shipping_streets", fieldError.getField()); + assertEquals("must be present and a string", fieldError.getMessage()); } } From ba3a86f7cdbc71b52fd5380dd01db9ff58324f43 Mon Sep 17 00:00:00 2001 From: Justintime50 <39606064+Justintime50@users.noreply.github.com> Date: Wed, 26 Feb 2025 14:18:51 -0700 Subject: [PATCH 6/7] docs: add info to changelog --- CHANGELOG.md | 5 +++++ .../model/AddressVerificationFieldError.java | 20 +++++++++---------- src/test/java/com/easypost/AddressTest.java | 1 + 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b660022db..46be9d20d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ ## Next Release - Adds `WebhookCustomHeader` model, allowing `custom_headers` to be passed when creating/updating a webhook +- Fixes error parsing + - Allows for alternative format of `errors` field (previously we deserialized the `errors` field into a list of `Error` objects; however, sometimes the errors are simply a list of strings. This change make the `errors` field a list of `Object` allowing for either the new `FieldError` object or a list of strings. Users will need to check for the type of error returned and handle appropriately) + - Removed the unused `Error` model + - Added an explicit `AddressVerificationFieldError` model + - The `BetaPaymentRefund` now uses a list of `FieldError` instead of `Error` for the `errors` field - Corrects payload wrapping for updating a webhook - Bumps dependencies diff --git a/src/main/java/com/easypost/model/AddressVerificationFieldError.java b/src/main/java/com/easypost/model/AddressVerificationFieldError.java index 805b3b80c..75d512cbb 100644 --- a/src/main/java/com/easypost/model/AddressVerificationFieldError.java +++ b/src/main/java/com/easypost/model/AddressVerificationFieldError.java @@ -5,11 +5,20 @@ @Getter public final class AddressVerificationFieldError { + private String message; private String code; private String field; - private String message; private String suggestion; + /** + * Set the message of this error object. + * + * @param message The error message. + */ + void setMessage(final String message) { + this.message = message; + } + /** * Set the code of this error object. * @@ -28,15 +37,6 @@ void setField(final String field) { this.field = field; } - /** - * Set the message of this error object. - * - * @param message The error message. - */ - void setMessage(final String message) { - this.message = message; - } - /** * Set the suggestion of this error object. * diff --git a/src/test/java/com/easypost/AddressTest.java b/src/test/java/com/easypost/AddressTest.java index b95d74b37..d535a0b93 100644 --- a/src/test/java/com/easypost/AddressTest.java +++ b/src/test/java/com/easypost/AddressTest.java @@ -90,6 +90,7 @@ public void testCreateVerify() throws EasyPostException { address = vcr.client.address.create(addressData); assertInstanceOf(Address.class, address); + assertEquals(false, address.getVerifications().getDelivery().getSuccess()); assertInstanceOf(AddressDetail.class, address.getVerifications().getDelivery().getDetails()); AddressVerificationFieldError addressVerificationFieldErrorGetDelivery = address.getVerifications().getDelivery().getErrors().get(0); From 61d88e0c5b6f7d6e61d646a77f63582f1b930ae9 Mon Sep 17 00:00:00 2001 From: Justintime50 <39606064+Justintime50@users.noreply.github.com> Date: Wed, 26 Feb 2025 14:21:59 -0700 Subject: [PATCH 7/7] fix: lint --- src/main/java/com/easypost/exception/APIException.java | 5 +++-- .../easypost/model/AddressVerificationFieldError.java | 1 - .../java/com/easypost/model/ErrorDeserializer.java | 2 -- src/main/java/com/easypost/model/FieldError.java | 1 - src/test/java/com/easypost/AddressTest.java | 10 ++++++++-- src/test/java/com/easypost/ErrorTest.java | 2 -- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/easypost/exception/APIException.java b/src/main/java/com/easypost/exception/APIException.java index 2956bd24f..991a783c1 100644 --- a/src/main/java/com/easypost/exception/APIException.java +++ b/src/main/java/com/easypost/exception/APIException.java @@ -60,7 +60,8 @@ public APIException(final String message, final String code, final List * @param statusCode the exception status code * @param ex the exception cause */ - public APIException(final String message, final String code, final List errors, final Integer statusCode, final Throwable ex) { + public APIException(final String message, final String code, final List errors, + final Integer statusCode, final Throwable ex) { super(message); this.message = message; this.code = code; @@ -70,7 +71,7 @@ public APIException(final String message, final String code, final List /** * Get status code of the error object. - * + * * @return statusCode the status code of the error object */ public Integer getStatusCode() { diff --git a/src/main/java/com/easypost/model/AddressVerificationFieldError.java b/src/main/java/com/easypost/model/AddressVerificationFieldError.java index 75d512cbb..64b9e86dc 100644 --- a/src/main/java/com/easypost/model/AddressVerificationFieldError.java +++ b/src/main/java/com/easypost/model/AddressVerificationFieldError.java @@ -1,6 +1,5 @@ package com.easypost.model; -import java.util.List; import lombok.Getter; @Getter diff --git a/src/main/java/com/easypost/model/ErrorDeserializer.java b/src/main/java/com/easypost/model/ErrorDeserializer.java index dbdab3c3b..a8322d1db 100644 --- a/src/main/java/com/easypost/model/ErrorDeserializer.java +++ b/src/main/java/com/easypost/model/ErrorDeserializer.java @@ -2,14 +2,12 @@ import com.easypost.Constants; import com.easypost.exception.APIException; -import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; import java.lang.reflect.Type; import java.util.ArrayList; diff --git a/src/main/java/com/easypost/model/FieldError.java b/src/main/java/com/easypost/model/FieldError.java index 9d8b5cbdd..134f273a7 100644 --- a/src/main/java/com/easypost/model/FieldError.java +++ b/src/main/java/com/easypost/model/FieldError.java @@ -1,6 +1,5 @@ package com.easypost.model; -import java.util.List; import lombok.Getter; @Getter diff --git a/src/test/java/com/easypost/AddressTest.java b/src/test/java/com/easypost/AddressTest.java index d535a0b93..87b3dae58 100644 --- a/src/test/java/com/easypost/AddressTest.java +++ b/src/test/java/com/easypost/AddressTest.java @@ -93,7 +93,10 @@ public void testCreateVerify() throws EasyPostException { assertEquals(false, address.getVerifications().getDelivery().getSuccess()); assertInstanceOf(AddressDetail.class, address.getVerifications().getDelivery().getDetails()); - AddressVerificationFieldError addressVerificationFieldErrorGetDelivery = address.getVerifications().getDelivery().getErrors().get(0); + AddressVerificationFieldError addressVerificationFieldErrorGetDelivery = address.getVerifications() + .getDelivery() + .getErrors() + .get(0); assertEquals("E.ADDRESS.NOT_FOUND", addressVerificationFieldErrorGetDelivery.getCode()); assertEquals("address", addressVerificationFieldErrorGetDelivery.getField()); assertNull(addressVerificationFieldErrorGetDelivery.getSuggestion()); @@ -101,7 +104,10 @@ public void testCreateVerify() throws EasyPostException { assertEquals(false, address.getVerifications().getZip4().getSuccess()); assertNull(address.getVerifications().getZip4().getDetails()); - AddressVerificationFieldError addressVerificationFieldErrorZip4 = address.getVerifications().getZip4().getErrors().get(0); + AddressVerificationFieldError addressVerificationFieldErrorZip4 = address.getVerifications() + .getZip4() + .getErrors() + .get(0); assertEquals("E.ADDRESS.NOT_FOUND", addressVerificationFieldErrorZip4.getCode()); assertEquals("address", addressVerificationFieldErrorZip4.getField()); assertNull(addressVerificationFieldErrorZip4.getSuggestion()); diff --git a/src/test/java/com/easypost/ErrorTest.java b/src/test/java/com/easypost/ErrorTest.java index 7986bcfea..49e142a5f 100644 --- a/src/test/java/com/easypost/ErrorTest.java +++ b/src/test/java/com/easypost/ErrorTest.java @@ -21,8 +21,6 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import com.easypost.model.FieldError; - import java.util.HashMap; import java.util.Map;