diff --git a/gax-java/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonApiExceptionFactory.java b/gax-java/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonApiExceptionFactory.java index a48f0b5a24..55c9a68b52 100644 --- a/gax-java/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonApiExceptionFactory.java +++ b/gax-java/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonApiExceptionFactory.java @@ -32,9 +32,11 @@ import com.google.api.client.http.HttpResponseException; import com.google.api.gax.rpc.ApiException; import com.google.api.gax.rpc.ApiExceptionFactory; +import com.google.api.gax.rpc.ErrorDetails; import com.google.api.gax.rpc.StatusCode; import com.google.api.gax.rpc.StatusCode.Code; import com.google.common.collect.ImmutableSet; +import com.google.rpc.Status; import java.util.Set; import java.util.concurrent.CancellationException; @@ -51,7 +53,21 @@ ApiException create(Throwable throwable) { StatusCode statusCode = HttpJsonStatusCode.of(e.getStatusCode()); boolean canRetry = retryableCodes.contains(statusCode.getCode()); String message = e.getStatusMessage(); - return createApiException(throwable, statusCode, message, canRetry); + Status status = HttpJsonErrorParser.parseStatus(e.getContent()); + + if (!status.getMessage().isEmpty()) { + message = status.getMessage(); + } + + ErrorDetails errorDetails = + ErrorDetails.builder().setRawErrorMessages(status.getDetailsList()).build(); + + if (message == null) { + message = throwable.toString(); + } + + return ApiExceptionFactory.createException( + message, throwable, statusCode, canRetry, errorDetails); } else if (throwable instanceof HttpJsonStatusRuntimeException) { HttpJsonStatusRuntimeException e = (HttpJsonStatusRuntimeException) throwable; StatusCode statusCode = HttpJsonStatusCode.of(e.getStatusCode()); diff --git a/gax-java/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonApiExceptionFactoryTest.java b/gax-java/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonApiExceptionFactoryTest.java new file mode 100644 index 0000000000..2c7d01c47b --- /dev/null +++ b/gax-java/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonApiExceptionFactoryTest.java @@ -0,0 +1,151 @@ +/* + * Copyright 2026 Google LLC + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.google.api.gax.httpjson; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpResponseException; +import com.google.api.gax.rpc.ApiException; +import com.google.api.gax.rpc.ErrorDetails; +import com.google.api.gax.rpc.StatusCode.Code; +import com.google.common.collect.ImmutableSet; +import org.junit.jupiter.api.Test; + +class HttpJsonApiExceptionFactoryTest { + + @Test + void testCreate_withAllFieldsPresent() { + String payload = + "{\n" + + " \"error\": {\n" + + " \"code\": 7,\n" + + " \"message\": \"The caller does not have permission\",\n" + + " \"details\": [\n" + + " {\n" + + " \"@type\": \"type.googleapis.com/google.rpc.ErrorInfo\",\n" + + " \"reason\": \"SERVICE_DISABLED\",\n" + + " \"domain\": \"googleapis.com\",\n" + + " \"metadata\": {\n" + + " \"service\": \"pubsub.googleapis.com\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + + HttpResponseException exception = + new HttpResponseException.Builder(403, "Forbidden", new HttpHeaders()) + .setContent(payload) + .build(); + + HttpJsonApiExceptionFactory factory = + new HttpJsonApiExceptionFactory(ImmutableSet.of(Code.UNAVAILABLE)); + ApiException apiException = factory.create(exception); + + // The status code should be derived from the JSON code (7), ignoring HTTP code (403). + assertThat(apiException.getStatusCode().getCode()).isEqualTo(Code.PERMISSION_DENIED); + assertThat(apiException.isRetryable()).isFalse(); + // The message should be overridden by the JSON message + assertThat(apiException.getMessage()).contains("The caller does not have permission"); + + ErrorDetails details = apiException.getErrorDetails(); + assertThat(details).isNotNull(); + assertThat(details.getErrorInfo()).isNotNull(); + assertThat(details.getErrorInfo().getReason()).isEqualTo("SERVICE_DISABLED"); + assertThat(details.getErrorInfo().getDomain()).isEqualTo("googleapis.com"); + assertThat(details.getErrorInfo().getMetadataMap().get("service")) + .isEqualTo("pubsub.googleapis.com"); + } + + @Test + void testCreate_withOkStatusNoMessageNoDetails() { + String payload = "{\n \"error\": {\n \"code\": 0\n }\n}"; + + HttpResponseException exception = + new HttpResponseException.Builder(403, "Forbidden", new HttpHeaders()) + .setContent(payload) + .build(); + + HttpJsonApiExceptionFactory factory = + new HttpJsonApiExceptionFactory(ImmutableSet.of(Code.UNAVAILABLE)); + ApiException apiException = factory.create(exception); + + // Because code is 0 (OK), it falls back to the HTTP status code (403 -> PERMISSION_DENIED). + assertThat(apiException.getStatusCode().getCode()).isEqualTo(Code.PERMISSION_DENIED); + assertThat(apiException.isRetryable()).isFalse(); + // Because there is no message in the payload, it falls back to the HTTP status message. + assertThat(apiException.getMessage()).contains("Forbidden"); + // Details are unconditionally built, but empty. + assertThat(apiException.getErrorDetails()).isNotNull(); + assertThat(apiException.getErrorDetails().getErrorInfo()).isNull(); + } + + @Test + void testCreate_withMessageOverridesHttpStatusMessage() { + String payload = + "{\n" + + " \"error\": {\n" + + " \"message\": \"Custom detailed error message from server\"\n" + + " }\n" + + "}"; + + // Transport layer returned generic "Bad Request" phrase + HttpResponseException exception = + new HttpResponseException.Builder(400, "Bad Request", new HttpHeaders()) + .setContent(payload) + .build(); + + HttpJsonApiExceptionFactory factory = + new HttpJsonApiExceptionFactory(ImmutableSet.of(Code.UNAVAILABLE)); + ApiException apiException = factory.create(exception); + + assertThat(apiException.getMessage()).contains("Custom detailed error message from server"); + assertThat(apiException.getMessage()).doesNotContain("Bad Request"); + } + + @Test + void testCreate_withoutErrorDetails() { + HttpResponseException exception = + new HttpResponseException.Builder(503, "Service Unavailable", new HttpHeaders()) + .setContent("plain text error") + .build(); + + HttpJsonApiExceptionFactory factory = + new HttpJsonApiExceptionFactory(ImmutableSet.of(Code.UNAVAILABLE)); + ApiException apiException = factory.create(exception); + + assertThat(apiException.getStatusCode().getCode()).isEqualTo(Code.UNAVAILABLE); + assertThat(apiException.isRetryable()).isTrue(); + // Plain text error parsing will still generate an empty ErrorDetails + assertThat(apiException.getErrorDetails()).isNotNull(); + assertThat(apiException.getErrorDetails().getErrorInfo()).isNull(); + } +} diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/AbortedException.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/AbortedException.java index 4cd2e31b6e..57b1b222c1 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/AbortedException.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/AbortedException.java @@ -47,4 +47,13 @@ public AbortedException( Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { super(cause, statusCode, retryable, errorDetails); } + + public AbortedException( + String message, + Throwable cause, + StatusCode statusCode, + boolean retryable, + ErrorDetails errorDetails) { + super(message, cause, statusCode, retryable, errorDetails); + } } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/AlreadyExistsException.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/AlreadyExistsException.java index 6ee118898c..91a61bb89b 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/AlreadyExistsException.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/AlreadyExistsException.java @@ -47,4 +47,13 @@ public AlreadyExistsException( Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { super(cause, statusCode, retryable, errorDetails); } + + public AlreadyExistsException( + String message, + Throwable cause, + StatusCode statusCode, + boolean retryable, + ErrorDetails errorDetails) { + super(message, cause, statusCode, retryable, errorDetails); + } } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/ApiException.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/ApiException.java index 3722b894ee..be8d26811e 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/ApiException.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/ApiException.java @@ -60,6 +60,18 @@ public ApiException( this.errorDetails = errorDetails; } + public ApiException( + String message, + Throwable cause, + StatusCode statusCode, + boolean retryable, + ErrorDetails errorDetails) { + super(message, cause); + this.statusCode = Preconditions.checkNotNull(statusCode); + this.retryable = retryable; + this.errorDetails = errorDetails; + } + /** Returns whether the failed request can be retried. */ public boolean isRetryable() { return retryable; diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/ApiExceptionFactory.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/ApiExceptionFactory.java index 4ca5f41c7b..2cc836b295 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/ApiExceptionFactory.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/ApiExceptionFactory.java @@ -83,40 +83,50 @@ public static ApiException createException( public static ApiException createException( Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { + return createException( + cause == null ? null : cause.toString(), cause, statusCode, retryable, errorDetails); + } + + public static ApiException createException( + String message, + Throwable cause, + StatusCode statusCode, + boolean retryable, + ErrorDetails errorDetails) { switch (statusCode.getCode()) { case CANCELLED: - return new CancelledException(cause, statusCode, retryable, errorDetails); + return new CancelledException(message, cause, statusCode, retryable, errorDetails); case NOT_FOUND: - return new NotFoundException(cause, statusCode, retryable, errorDetails); + return new NotFoundException(message, cause, statusCode, retryable, errorDetails); case INVALID_ARGUMENT: - return new InvalidArgumentException(cause, statusCode, retryable, errorDetails); + return new InvalidArgumentException(message, cause, statusCode, retryable, errorDetails); case DEADLINE_EXCEEDED: - return new DeadlineExceededException(cause, statusCode, retryable, errorDetails); + return new DeadlineExceededException(message, cause, statusCode, retryable, errorDetails); case ALREADY_EXISTS: - return new AlreadyExistsException(cause, statusCode, retryable, errorDetails); + return new AlreadyExistsException(message, cause, statusCode, retryable, errorDetails); case PERMISSION_DENIED: - return new PermissionDeniedException(cause, statusCode, retryable, errorDetails); + return new PermissionDeniedException(message, cause, statusCode, retryable, errorDetails); case RESOURCE_EXHAUSTED: - return new ResourceExhaustedException(cause, statusCode, retryable, errorDetails); + return new ResourceExhaustedException(message, cause, statusCode, retryable, errorDetails); case FAILED_PRECONDITION: - return new FailedPreconditionException(cause, statusCode, retryable, errorDetails); + return new FailedPreconditionException(message, cause, statusCode, retryable, errorDetails); case ABORTED: - return new AbortedException(cause, statusCode, retryable, errorDetails); + return new AbortedException(message, cause, statusCode, retryable, errorDetails); case OUT_OF_RANGE: - return new OutOfRangeException(cause, statusCode, retryable, errorDetails); + return new OutOfRangeException(message, cause, statusCode, retryable, errorDetails); case UNIMPLEMENTED: - return new UnimplementedException(cause, statusCode, retryable, errorDetails); + return new UnimplementedException(message, cause, statusCode, retryable, errorDetails); case INTERNAL: - return new InternalException(cause, statusCode, retryable, errorDetails); + return new InternalException(message, cause, statusCode, retryable, errorDetails); case UNAVAILABLE: - return new UnavailableException(cause, statusCode, retryable, errorDetails); + return new UnavailableException(message, cause, statusCode, retryable, errorDetails); case DATA_LOSS: - return new DataLossException(cause, statusCode, retryable, errorDetails); + return new DataLossException(message, cause, statusCode, retryable, errorDetails); case UNAUTHENTICATED: - return new UnauthenticatedException(cause, statusCode, retryable, errorDetails); + return new UnauthenticatedException(message, cause, statusCode, retryable, errorDetails); case UNKNOWN: // Fall through. default: - return new UnknownException(cause, statusCode, retryable, errorDetails); + return new UnknownException(message, cause, statusCode, retryable, errorDetails); } } } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/CancelledException.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/CancelledException.java index 7bc15f04c3..f966c00315 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/CancelledException.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/CancelledException.java @@ -44,4 +44,13 @@ public CancelledException( Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { super(cause, statusCode, retryable, errorDetails); } + + public CancelledException( + String message, + Throwable cause, + StatusCode statusCode, + boolean retryable, + ErrorDetails errorDetails) { + super(message, cause, statusCode, retryable, errorDetails); + } } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/DataLossException.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/DataLossException.java index e3d9a8107c..f64d83c786 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/DataLossException.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/DataLossException.java @@ -44,4 +44,13 @@ public DataLossException( Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { super(cause, statusCode, retryable, errorDetails); } + + public DataLossException( + String message, + Throwable cause, + StatusCode statusCode, + boolean retryable, + ErrorDetails errorDetails) { + super(message, cause, statusCode, retryable, errorDetails); + } } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/DeadlineExceededException.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/DeadlineExceededException.java index 37b5d8db00..1ac5a4cdcd 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/DeadlineExceededException.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/DeadlineExceededException.java @@ -49,4 +49,13 @@ public DeadlineExceededException( Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { super(cause, statusCode, retryable, errorDetails); } + + public DeadlineExceededException( + String message, + Throwable cause, + StatusCode statusCode, + boolean retryable, + ErrorDetails errorDetails) { + super(message, cause, statusCode, retryable, errorDetails); + } } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/FailedPreconditionException.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/FailedPreconditionException.java index e1b3ec75e9..56655d3a24 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/FailedPreconditionException.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/FailedPreconditionException.java @@ -48,4 +48,13 @@ public FailedPreconditionException( Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { super(cause, statusCode, retryable, errorDetails); } + + public FailedPreconditionException( + String message, + Throwable cause, + StatusCode statusCode, + boolean retryable, + ErrorDetails errorDetails) { + super(message, cause, statusCode, retryable, errorDetails); + } } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/InternalException.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/InternalException.java index 3d5763f060..af2c9fa80e 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/InternalException.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/InternalException.java @@ -47,4 +47,13 @@ public InternalException( Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { super(cause, statusCode, retryable, errorDetails); } + + public InternalException( + String message, + Throwable cause, + StatusCode statusCode, + boolean retryable, + ErrorDetails errorDetails) { + super(message, cause, statusCode, retryable, errorDetails); + } } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/InvalidArgumentException.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/InvalidArgumentException.java index 6b0ccc6f61..430640b976 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/InvalidArgumentException.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/InvalidArgumentException.java @@ -48,4 +48,13 @@ public InvalidArgumentException( Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { super(cause, statusCode, retryable, errorDetails); } + + public InvalidArgumentException( + String message, + Throwable cause, + StatusCode statusCode, + boolean retryable, + ErrorDetails errorDetails) { + super(message, cause, statusCode, retryable, errorDetails); + } } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/NotFoundException.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/NotFoundException.java index ce8b0b1d7e..86e86a32af 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/NotFoundException.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/NotFoundException.java @@ -44,4 +44,13 @@ public NotFoundException( Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { super(cause, statusCode, retryable, errorDetails); } + + public NotFoundException( + String message, + Throwable cause, + StatusCode statusCode, + boolean retryable, + ErrorDetails errorDetails) { + super(message, cause, statusCode, retryable, errorDetails); + } } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/OutOfRangeException.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/OutOfRangeException.java index 33ecb38cab..10e68e12fb 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/OutOfRangeException.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/OutOfRangeException.java @@ -47,4 +47,13 @@ public OutOfRangeException( Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { super(cause, statusCode, retryable, errorDetails); } + + public OutOfRangeException( + String message, + Throwable cause, + StatusCode statusCode, + boolean retryable, + ErrorDetails errorDetails) { + super(message, cause, statusCode, retryable, errorDetails); + } } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/PermissionDeniedException.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/PermissionDeniedException.java index c9e7515976..14e92d9d4f 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/PermissionDeniedException.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/PermissionDeniedException.java @@ -44,4 +44,13 @@ public PermissionDeniedException( Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { super(cause, statusCode, retryable, errorDetails); } + + public PermissionDeniedException( + String message, + Throwable cause, + StatusCode statusCode, + boolean retryable, + ErrorDetails errorDetails) { + super(message, cause, statusCode, retryable, errorDetails); + } } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/ResourceExhaustedException.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/ResourceExhaustedException.java index 2561c54ce7..069100bb0d 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/ResourceExhaustedException.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/ResourceExhaustedException.java @@ -47,4 +47,13 @@ public ResourceExhaustedException( Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { super(cause, statusCode, retryable, errorDetails); } + + public ResourceExhaustedException( + String message, + Throwable cause, + StatusCode statusCode, + boolean retryable, + ErrorDetails errorDetails) { + super(message, cause, statusCode, retryable, errorDetails); + } } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/UnauthenticatedException.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/UnauthenticatedException.java index 6daeece5a9..9f6954d65a 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/UnauthenticatedException.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/UnauthenticatedException.java @@ -47,4 +47,13 @@ public UnauthenticatedException( Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { super(cause, statusCode, retryable, errorDetails); } + + public UnauthenticatedException( + String message, + Throwable cause, + StatusCode statusCode, + boolean retryable, + ErrorDetails errorDetails) { + super(message, cause, statusCode, retryable, errorDetails); + } } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/UnavailableException.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/UnavailableException.java index 96fbc8d280..7b564e085f 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/UnavailableException.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/UnavailableException.java @@ -47,4 +47,13 @@ public UnavailableException( Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { super(cause, statusCode, retryable, errorDetails); } + + public UnavailableException( + String message, + Throwable cause, + StatusCode statusCode, + boolean retryable, + ErrorDetails errorDetails) { + super(message, cause, statusCode, retryable, errorDetails); + } } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/UnimplementedException.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/UnimplementedException.java index 8e042f4414..8c6c2f77f3 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/UnimplementedException.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/UnimplementedException.java @@ -46,4 +46,13 @@ public UnimplementedException( Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { super(cause, statusCode, retryable, errorDetails); } + + public UnimplementedException( + String message, + Throwable cause, + StatusCode statusCode, + boolean retryable, + ErrorDetails errorDetails) { + super(message, cause, statusCode, retryable, errorDetails); + } } diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/UnknownException.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/UnknownException.java index a3ebe35991..f6fe80138c 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/UnknownException.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/UnknownException.java @@ -49,4 +49,13 @@ public UnknownException( Throwable cause, StatusCode statusCode, boolean retryable, ErrorDetails errorDetails) { super(cause, statusCode, retryable, errorDetails); } + + public UnknownException( + String message, + Throwable cause, + StatusCode statusCode, + boolean retryable, + ErrorDetails errorDetails) { + super(message, cause, statusCode, retryable, errorDetails); + } }