Skip to content

Commit ebe2b48

Browse files
authoredDec 22, 2024··
api: StatusRuntimeException without stacktrace - Android compatibility (#11072)
This is an alternative to e36f099 that avoids the "fillInStaceTrace" constructor which is only available starting at Android API level 24.
1 parent 6516c73 commit ebe2b48

File tree

9 files changed

+56
-38
lines changed

9 files changed

+56
-38
lines changed
 

‎api/build.gradle

+5-7
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,11 @@ dependencies {
5454
extension = "signature"
5555
}
5656
}
57-
// TODO: Temporarily disabled until StatusException is fixed.
58-
// Context: https://github.com/grpc/grpc-java/pull/11066
59-
//signature (libraries.signature.android) {
60-
// artifact {
61-
// extension = "signature"
62-
// }
63-
//}
57+
signature (libraries.signature.android) {
58+
artifact {
59+
extension = "signature"
60+
}
61+
}
6462
}
6563

6664
tasks.named("javadoc").configure {

‎api/src/main/java/io/grpc/InternalStatus.java

+4-5
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,11 @@ private InternalStatus() {}
3838
public static final Metadata.Key<Status> CODE_KEY = Status.CODE_KEY;
3939

4040
/**
41-
* Create a new {@link StatusRuntimeException} with the internal option of skipping the filling
42-
* of the stack trace.
41+
* Create a new {@link StatusRuntimeException} skipping the filling of the stack trace.
4342
*/
4443
@Internal
45-
public static final StatusRuntimeException asRuntimeException(Status status,
46-
@Nullable Metadata trailers, boolean fillInStackTrace) {
47-
return new StatusRuntimeException(status, trailers, fillInStackTrace);
44+
public static StatusRuntimeException asRuntimeExceptionWithoutStacktrace(Status status,
45+
@Nullable Metadata trailers) {
46+
return new InternalStatusRuntimeException(status, trailers);
4847
}
4948
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2015 The gRPC Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.grpc;
18+
19+
import javax.annotation.Nullable;
20+
21+
/**
22+
* StatusRuntimeException without stack trace, implemented as a subclass, as the
23+
* {@code String, Throwable, boolean, boolean} constructor is not available in the supported
24+
* version of Android.
25+
*
26+
* @see StatusRuntimeException
27+
*/
28+
class InternalStatusRuntimeException extends StatusRuntimeException {
29+
private static final long serialVersionUID = 0;
30+
31+
public InternalStatusRuntimeException(Status status, @Nullable Metadata trailers) {
32+
super(status, trailers);
33+
}
34+
35+
@Override
36+
public synchronized Throwable fillInStackTrace() {
37+
return this;
38+
}
39+
}

‎api/src/main/java/io/grpc/StatusException.java

+1-6
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,7 @@ public StatusException(Status status) {
4444
* @since 1.0.0
4545
*/
4646
public StatusException(Status status, @Nullable Metadata trailers) {
47-
this(status, trailers, /*fillInStackTrace=*/ true);
48-
}
49-
50-
StatusException(Status status, @Nullable Metadata trailers, boolean fillInStackTrace) {
51-
super(Status.formatThrowableMessage(status), status.getCause(),
52-
/* enableSuppression */ true, /* writableStackTrace */fillInStackTrace);
47+
super(Status.formatThrowableMessage(status), status.getCause());
5348
this.status = status;
5449
this.trailers = trailers;
5550
}

‎api/src/main/java/io/grpc/StatusRuntimeException.java

+1-6
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,7 @@ public StatusRuntimeException(Status status) {
4545
* @since 1.0.0
4646
*/
4747
public StatusRuntimeException(Status status, @Nullable Metadata trailers) {
48-
this(status, trailers, /*fillInStackTrace=*/ true);
49-
}
50-
51-
StatusRuntimeException(Status status, @Nullable Metadata trailers, boolean fillInStackTrace) {
52-
super(Status.formatThrowableMessage(status), status.getCause(),
53-
/* enable suppressions */ true, /* writableStackTrace */ fillInStackTrace);
48+
super(Status.formatThrowableMessage(status), status.getCause());
5449
this.status = status;
5550
this.trailers = trailers;
5651
}

‎api/src/test/java/io/grpc/StatusExceptionTest.java

-8
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,6 @@
2828
@RunWith(JUnit4.class)
2929
public class StatusExceptionTest {
3030

31-
@Test
32-
public void internalCtorRemovesStack() {
33-
StackTraceElement[] trace =
34-
new StatusException(Status.CANCELLED, null, false) {}.getStackTrace();
35-
36-
assertThat(trace).isEmpty();
37-
}
38-
3931
@Test
4032
public void normalCtorKeepsStack() {
4133
StackTraceElement[] trace =

‎api/src/test/java/io/grpc/StatusRuntimeExceptionTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public class StatusRuntimeExceptionTest {
3131
@Test
3232
public void internalCtorRemovesStack() {
3333
StackTraceElement[] trace =
34-
new StatusRuntimeException(Status.CANCELLED, null, false) {}.getStackTrace();
34+
new InternalStatusRuntimeException(Status.CANCELLED, null) {}.getStackTrace();
3535

3636
assertThat(trace).isEmpty();
3737
}

‎core/src/main/java/io/grpc/internal/ServerCallImpl.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -373,10 +373,10 @@ private void closedInternal(Status status) {
373373
} else {
374374
call.cancelled = true;
375375
listener.onCancel();
376-
// The status will not have a cause in all failure scenarios but we want to make sure
376+
// The status will not have a cause in all failure scenarios, but we want to make sure
377377
// we always cancel the context with one to keep the context cancelled state consistent.
378-
cancelCause = InternalStatus.asRuntimeException(
379-
Status.CANCELLED.withDescription("RPC cancelled"), null, false);
378+
cancelCause = InternalStatus.asRuntimeExceptionWithoutStacktrace(
379+
Status.CANCELLED.withDescription("RPC cancelled"), null);
380380
}
381381
} finally {
382382
// Cancel context after delivering RPC closure notification to allow the application to

‎core/src/main/java/io/grpc/internal/ServerImpl.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -887,8 +887,8 @@ private void closedInternal(final Status status) {
887887
// failed status has an exception we will create one here if needed.
888888
Throwable cancelCause = status.getCause();
889889
if (cancelCause == null) {
890-
cancelCause = InternalStatus.asRuntimeException(
891-
Status.CANCELLED.withDescription("RPC cancelled"), null, false);
890+
cancelCause = InternalStatus.asRuntimeExceptionWithoutStacktrace(
891+
Status.CANCELLED.withDescription("RPC cancelled"), null);
892892
}
893893

894894
// The callExecutor might be busy doing user work. To avoid waiting, use an executor that

0 commit comments

Comments
 (0)
Please sign in to comment.