16
16
17
17
package com .google .cloud .spanner ;
18
18
19
+ import com .google .api .gax .rpc .ApiException ;
20
+ import com .google .api .gax .rpc .ErrorDetails ;
19
21
import com .google .cloud .grpc .BaseGrpcServiceException ;
20
22
import com .google .common .base .Preconditions ;
21
23
import com .google .protobuf .util .Durations ;
24
26
import io .grpc .Metadata ;
25
27
import io .grpc .Status ;
26
28
import io .grpc .protobuf .ProtoUtils ;
29
+ import java .util .Map ;
27
30
import javax .annotation .Nullable ;
28
31
29
32
/** Base exception type for all exceptions produced by the Cloud Spanner service. */
@@ -36,8 +39,9 @@ public abstract static class ResourceNotFoundException extends SpannerException
36
39
DoNotConstructDirectly token ,
37
40
@ Nullable String message ,
38
41
ResourceInfo resourceInfo ,
39
- @ Nullable Throwable cause ) {
40
- super (token , ErrorCode .NOT_FOUND , /* retryable */ false , message , cause );
42
+ @ Nullable Throwable cause ,
43
+ @ Nullable ApiException apiException ) {
44
+ super (token , ErrorCode .NOT_FOUND , /* retryable */ false , message , cause , apiException );
41
45
this .resourceInfo = resourceInfo ;
42
46
}
43
47
@@ -51,6 +55,7 @@ public String getResourceName() {
51
55
ProtoUtils .keyForProto (RetryInfo .getDefaultInstance ());
52
56
53
57
private final ErrorCode code ;
58
+ private final ApiException apiException ;
54
59
55
60
/** Private constructor. Use {@link SpannerExceptionFactory} to create instances. */
56
61
SpannerException (
@@ -59,11 +64,23 @@ public String getResourceName() {
59
64
boolean retryable ,
60
65
@ Nullable String message ,
61
66
@ Nullable Throwable cause ) {
67
+ this (token , code , retryable , message , cause , null );
68
+ }
69
+
70
+ /** Private constructor. Use {@link SpannerExceptionFactory} to create instances. */
71
+ SpannerException (
72
+ DoNotConstructDirectly token ,
73
+ ErrorCode code ,
74
+ boolean retryable ,
75
+ @ Nullable String message ,
76
+ @ Nullable Throwable cause ,
77
+ @ Nullable ApiException apiException ) {
62
78
super (message , cause , code .getCode (), retryable );
63
79
if (token != DoNotConstructDirectly .ALLOWED ) {
64
80
throw new AssertionError ("Do not construct directly: use SpannerExceptionFactory" );
65
81
}
66
82
this .code = Preconditions .checkNotNull (code );
83
+ this .apiException = apiException ;
67
84
}
68
85
69
86
/** Returns the error code associated with this exception. */
@@ -95,4 +112,67 @@ static long extractRetryDelay(Throwable cause) {
95
112
}
96
113
return -1L ;
97
114
}
115
+
116
+ /**
117
+ * Checks the underlying reason of the exception and if it's {@link ApiException} then return the
118
+ * reason otherwise null.
119
+ *
120
+ * @see <a
121
+ * href="https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L117">Reason</a>
122
+ * @return the reason of an error.
123
+ */
124
+ public String getReason () {
125
+ if (this .apiException != null ) {
126
+ return this .apiException .getReason ();
127
+ }
128
+ return null ;
129
+ }
130
+
131
+ /**
132
+ * Checks the underlying reason of the exception and if it's {@link ApiException} then return the
133
+ * specific domain otherwise null.
134
+ *
135
+ * @see <a
136
+ * href="https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L125">Domain</a>
137
+ * @return the logical grouping to which the "reason" belongs.
138
+ */
139
+ public String getDomain () {
140
+ if (this .apiException != null ) {
141
+ return this .apiException .getDomain ();
142
+ }
143
+ return null ;
144
+ }
145
+
146
+ /**
147
+ * Checks the underlying reason of the exception and if it's {@link ApiException} then return a
148
+ * map of key-value pairs otherwise null.
149
+ *
150
+ * @see <a
151
+ * href="https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#L135">Metadata</a>
152
+ * @return the map of additional structured details about an error.
153
+ */
154
+ public Map <String , String > getMetadata () {
155
+ if (this .apiException != null ) {
156
+ return this .apiException .getMetadata ();
157
+ }
158
+ return null ;
159
+ }
160
+
161
+ /**
162
+ * Checks the underlying reason of the exception and if it's {@link ApiException} then return the
163
+ * ErrorDetails otherwise null.
164
+ *
165
+ * @see <a
166
+ * href="https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto">Status</a>
167
+ * @see <a
168
+ * href="https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto">Error
169
+ * Details</a>
170
+ * @return An object containing getters for structured objects from error_details.proto.
171
+ */
172
+ public ErrorDetails getErrorDetails () {
173
+ if (this .apiException != null ) {
174
+ return this .apiException .getErrorDetails ();
175
+ }
176
+ return null ;
177
+ }
98
178
}
0 commit comments