From 5c9b492318d6a996f7703ee83d91e0568cfe0c2a Mon Sep 17 00:00:00 2001 From: rtadepalli <105760760+rtadepalli@users.noreply.github.com> Date: Wed, 24 Apr 2024 21:05:54 -0400 Subject: [PATCH] Add `StatusProto.toStatusException` overload to accept `Throwable` (#11083) * Add `StatusProto.toStatusException` overload to accept `Throwable` --------- Co-authored-by: Eric Anderson --- .../java/io/grpc/protobuf/StatusProto.java | 19 +++++++++++++++++++ .../io/grpc/protobuf/StatusProtoTest.java | 8 ++++++++ 2 files changed, 27 insertions(+) diff --git a/protobuf/src/main/java/io/grpc/protobuf/StatusProto.java b/protobuf/src/main/java/io/grpc/protobuf/StatusProto.java index 988e1938af0..0ebc1e714f6 100644 --- a/protobuf/src/main/java/io/grpc/protobuf/StatusProto.java +++ b/protobuf/src/main/java/io/grpc/protobuf/StatusProto.java @@ -103,6 +103,25 @@ public static StatusException toStatusException( return toStatus(statusProto).asException(toMetadata(statusProto, metadata)); } + /** + * Convert a {@link com.google.rpc.Status} instance to a {@link StatusException} with additional + * metadata and the root exception thrown. The exception isn't propagated over the wire. + * + *

The returned {@link StatusException} will wrap a {@link Status} whose code and description + * are set from the code and message in {@code statusProto}. {@code statusProto} will be + * serialized and added to {@code metadata}. {@code metadata} will be set as the metadata of the + * returned {@link StatusException}. The {@link Throwable} is the exception that is set as the + * {@code cause} of the returned {@link StatusException}. + * + * @throws IllegalArgumentException if the value of {@code statusProto.getCode()} is not a valid + * gRPC status code. + * @since 1.3.0 + */ + public static StatusException toStatusException( + com.google.rpc.Status statusProto, Metadata metadata, Throwable cause) { + return toStatus(statusProto).withCause(cause).asException(toMetadata(statusProto, metadata)); + } + private static Status toStatus(com.google.rpc.Status statusProto) { Status status = Status.fromCodeValue(statusProto.getCode()); checkArgument(status.getCode().value() == statusProto.getCode(), "invalid status code"); diff --git a/protobuf/src/test/java/io/grpc/protobuf/StatusProtoTest.java b/protobuf/src/test/java/io/grpc/protobuf/StatusProtoTest.java index cf9c2c564ab..47c045bf952 100644 --- a/protobuf/src/test/java/io/grpc/protobuf/StatusProtoTest.java +++ b/protobuf/src/test/java/io/grpc/protobuf/StatusProtoTest.java @@ -176,6 +176,14 @@ public void fromThrowable_shouldReturnNullIfNoEmbeddedStatus() { assertNull(StatusProto.fromThrowable(nestedSe)); } + @Test + public void toStatusExceptionWithMetadataAndCause_shouldCaptureCause() { + RuntimeException exc = new RuntimeException("This is a test exception."); + StatusException se = StatusProto.toStatusException(STATUS_PROTO, new Metadata(), exc); + + assertEquals(exc, se.getCause()); + } + private static final Metadata.Key METADATA_KEY = Metadata.Key.of("test-metadata", Metadata.ASCII_STRING_MARSHALLER); private static final String METADATA_VALUE = "test metadata value";