diff --git a/api/build.gradle b/api/build.gradle index 4edfba7c0d8..6a75597ed55 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -54,13 +54,11 @@ dependencies { extension = "signature" } } - // TODO: Temporarily disabled until StatusException is fixed. - // Context: https://github.com/grpc/grpc-java/pull/11066 - //signature (libraries.signature.android) { - // artifact { - // extension = "signature" - // } - //} + signature (libraries.signature.android) { + artifact { + extension = "signature" + } + } } tasks.named("javadoc").configure { diff --git a/api/src/main/java/io/grpc/InternalStatus.java b/api/src/main/java/io/grpc/InternalStatus.java index b6549bb435f..56df1decf38 100644 --- a/api/src/main/java/io/grpc/InternalStatus.java +++ b/api/src/main/java/io/grpc/InternalStatus.java @@ -38,12 +38,11 @@ private InternalStatus() {} public static final Metadata.Key CODE_KEY = Status.CODE_KEY; /** - * Create a new {@link StatusRuntimeException} with the internal option of skipping the filling - * of the stack trace. + * Create a new {@link StatusRuntimeException} skipping the filling of the stack trace. */ @Internal - public static final StatusRuntimeException asRuntimeException(Status status, - @Nullable Metadata trailers, boolean fillInStackTrace) { - return new StatusRuntimeException(status, trailers, fillInStackTrace); + public static StatusRuntimeException asRuntimeExceptionWithoutStacktrace(Status status, + @Nullable Metadata trailers) { + return new InternalStatusRuntimeException(status, trailers); } } diff --git a/api/src/main/java/io/grpc/InternalStatusRuntimeException.java b/api/src/main/java/io/grpc/InternalStatusRuntimeException.java new file mode 100644 index 00000000000..6090b701f0b --- /dev/null +++ b/api/src/main/java/io/grpc/InternalStatusRuntimeException.java @@ -0,0 +1,39 @@ +/* + * Copyright 2015 The gRPC Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc; + +import javax.annotation.Nullable; + +/** + * StatusRuntimeException without stack trace, implemented as a subclass, as the + * {@code String, Throwable, boolean, boolean} constructor is not available in the supported + * version of Android. + * + * @see StatusRuntimeException + */ +class InternalStatusRuntimeException extends StatusRuntimeException { + private static final long serialVersionUID = 0; + + public InternalStatusRuntimeException(Status status, @Nullable Metadata trailers) { + super(status, trailers); + } + + @Override + public synchronized Throwable fillInStackTrace() { + return this; + } +} diff --git a/api/src/main/java/io/grpc/StatusException.java b/api/src/main/java/io/grpc/StatusException.java index b719f881132..f9416bf72e3 100644 --- a/api/src/main/java/io/grpc/StatusException.java +++ b/api/src/main/java/io/grpc/StatusException.java @@ -44,12 +44,7 @@ public StatusException(Status status) { * @since 1.0.0 */ public StatusException(Status status, @Nullable Metadata trailers) { - this(status, trailers, /*fillInStackTrace=*/ true); - } - - StatusException(Status status, @Nullable Metadata trailers, boolean fillInStackTrace) { - super(Status.formatThrowableMessage(status), status.getCause(), - /* enableSuppression */ true, /* writableStackTrace */fillInStackTrace); + super(Status.formatThrowableMessage(status), status.getCause()); this.status = status; this.trailers = trailers; } diff --git a/api/src/main/java/io/grpc/StatusRuntimeException.java b/api/src/main/java/io/grpc/StatusRuntimeException.java index 9465e4c38cd..dd22d6b2486 100644 --- a/api/src/main/java/io/grpc/StatusRuntimeException.java +++ b/api/src/main/java/io/grpc/StatusRuntimeException.java @@ -45,12 +45,7 @@ public StatusRuntimeException(Status status) { * @since 1.0.0 */ public StatusRuntimeException(Status status, @Nullable Metadata trailers) { - this(status, trailers, /*fillInStackTrace=*/ true); - } - - StatusRuntimeException(Status status, @Nullable Metadata trailers, boolean fillInStackTrace) { - super(Status.formatThrowableMessage(status), status.getCause(), - /* enable suppressions */ true, /* writableStackTrace */ fillInStackTrace); + super(Status.formatThrowableMessage(status), status.getCause()); this.status = status; this.trailers = trailers; } diff --git a/api/src/test/java/io/grpc/StatusExceptionTest.java b/api/src/test/java/io/grpc/StatusExceptionTest.java index dd0d12dccda..410cfb2289a 100644 --- a/api/src/test/java/io/grpc/StatusExceptionTest.java +++ b/api/src/test/java/io/grpc/StatusExceptionTest.java @@ -28,14 +28,6 @@ @RunWith(JUnit4.class) public class StatusExceptionTest { - @Test - public void internalCtorRemovesStack() { - StackTraceElement[] trace = - new StatusException(Status.CANCELLED, null, false) {}.getStackTrace(); - - assertThat(trace).isEmpty(); - } - @Test public void normalCtorKeepsStack() { StackTraceElement[] trace = diff --git a/api/src/test/java/io/grpc/StatusRuntimeExceptionTest.java b/api/src/test/java/io/grpc/StatusRuntimeExceptionTest.java index ab20c111254..d965ed86253 100644 --- a/api/src/test/java/io/grpc/StatusRuntimeExceptionTest.java +++ b/api/src/test/java/io/grpc/StatusRuntimeExceptionTest.java @@ -31,7 +31,7 @@ public class StatusRuntimeExceptionTest { @Test public void internalCtorRemovesStack() { StackTraceElement[] trace = - new StatusRuntimeException(Status.CANCELLED, null, false) {}.getStackTrace(); + new InternalStatusRuntimeException(Status.CANCELLED, null) {}.getStackTrace(); assertThat(trace).isEmpty(); } diff --git a/core/src/main/java/io/grpc/internal/ServerCallImpl.java b/core/src/main/java/io/grpc/internal/ServerCallImpl.java index dda36258e7c..e224384ce8f 100644 --- a/core/src/main/java/io/grpc/internal/ServerCallImpl.java +++ b/core/src/main/java/io/grpc/internal/ServerCallImpl.java @@ -373,10 +373,10 @@ private void closedInternal(Status status) { } else { call.cancelled = true; listener.onCancel(); - // The status will not have a cause in all failure scenarios but we want to make sure + // The status will not have a cause in all failure scenarios, but we want to make sure // we always cancel the context with one to keep the context cancelled state consistent. - cancelCause = InternalStatus.asRuntimeException( - Status.CANCELLED.withDescription("RPC cancelled"), null, false); + cancelCause = InternalStatus.asRuntimeExceptionWithoutStacktrace( + Status.CANCELLED.withDescription("RPC cancelled"), null); } } finally { // Cancel context after delivering RPC closure notification to allow the application to diff --git a/core/src/main/java/io/grpc/internal/ServerImpl.java b/core/src/main/java/io/grpc/internal/ServerImpl.java index cec2a13a301..eceb7d7a738 100644 --- a/core/src/main/java/io/grpc/internal/ServerImpl.java +++ b/core/src/main/java/io/grpc/internal/ServerImpl.java @@ -887,8 +887,8 @@ private void closedInternal(final Status status) { // failed status has an exception we will create one here if needed. Throwable cancelCause = status.getCause(); if (cancelCause == null) { - cancelCause = InternalStatus.asRuntimeException( - Status.CANCELLED.withDescription("RPC cancelled"), null, false); + cancelCause = InternalStatus.asRuntimeExceptionWithoutStacktrace( + Status.CANCELLED.withDescription("RPC cancelled"), null); } // The callExecutor might be busy doing user work. To avoid waiting, use an executor that