Skip to content

Commit 157e693

Browse files
committed
Error handling revamp for the project management API
1 parent 5d9ae69 commit 157e693

File tree

7 files changed

+236
-138
lines changed

7 files changed

+236
-138
lines changed

src/main/java/com/google/firebase/internal/ErrorHandlingHttpClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ public <V> V parse(IncomingHttpResponse response, Class<V> responseType) throws
116116
}
117117
}
118118

119-
private void parse(IncomingHttpResponse response, Object destination) throws T {
119+
public void parse(IncomingHttpResponse response, Object destination) throws T {
120120
try {
121121
JsonParser parser = jsonFactory.createJsonParser(response.getContent());
122122
parser.parse(destination);

src/main/java/com/google/firebase/projectmanagement/FirebaseProjectManagementException.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,27 @@
1515

1616
package com.google.firebase.projectmanagement;
1717

18+
import com.google.firebase.ErrorCode;
1819
import com.google.firebase.FirebaseException;
19-
import com.google.firebase.internal.Nullable;
20+
import com.google.firebase.IncomingHttpResponse;
21+
import com.google.firebase.database.annotations.Nullable;
22+
import com.google.firebase.internal.NonNull;
2023

2124
/**
2225
* An exception encountered while interacting with the Firebase Project Management Service.
2326
*/
24-
public class FirebaseProjectManagementException extends FirebaseException {
25-
FirebaseProjectManagementException(String detailMessage) {
26-
this(detailMessage, null);
27+
public final class FirebaseProjectManagementException extends FirebaseException {
28+
29+
FirebaseProjectManagementException(@NonNull FirebaseException base) {
30+
this(base, base.getMessage());
31+
}
32+
33+
FirebaseProjectManagementException(@NonNull FirebaseException base, @NonNull String message) {
34+
super(base.getErrorCodeNew(), message, base.getCause(), base.getHttpResponse());
2735
}
2836

29-
FirebaseProjectManagementException(String detailMessage, @Nullable Throwable cause) {
30-
super(detailMessage, cause);
37+
FirebaseProjectManagementException(
38+
@NonNull ErrorCode code, @NonNull String message, @Nullable IncomingHttpResponse response) {
39+
super(code, message, null, response);
3140
}
3241
}

src/main/java/com/google/firebase/projectmanagement/FirebaseProjectManagementServiceImpl.java

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@
3131
import com.google.common.base.Strings;
3232
import com.google.common.collect.ImmutableList;
3333
import com.google.common.collect.ImmutableMap;
34+
import com.google.firebase.ErrorCode;
3435
import com.google.firebase.FirebaseApp;
3536
import com.google.firebase.ImplFirebaseTrampolines;
3637
import com.google.firebase.internal.ApiClientUtils;
38+
import com.google.firebase.IncomingHttpResponse;
3739
import com.google.firebase.internal.CallableOperation;
3840
import java.nio.charset.StandardCharsets;
3941
import java.util.ArrayList;
@@ -318,20 +320,24 @@ protected String execute() throws FirebaseProjectManagementException {
318320
payloadBuilder.put("display_name", displayName);
319321
}
320322
OperationResponse operationResponseInstance = new OperationResponse();
321-
httpHelper.makePostRequest(
323+
IncomingHttpResponse response = httpHelper.makePostRequest(
322324
url, payloadBuilder.build(), operationResponseInstance, projectId, "Project ID");
323325
if (Strings.isNullOrEmpty(operationResponseInstance.name)) {
324-
throw HttpHelper.createFirebaseProjectManagementException(
326+
String message = buildMessage(
325327
namespace,
326328
"Bundle ID",
327-
"Unable to create App: server returned null operation name.",
328-
/* cause= */ null);
329+
"Unable to create App: server returned null operation name.");
330+
throw new FirebaseProjectManagementException(ErrorCode.INTERNAL, message, response);
329331
}
330332
return operationResponseInstance.name;
331333
}
332334
};
333335
}
334336

337+
private String buildMessage(String resourceId, String resourceIdName, String description) {
338+
return String.format("%s \"%s\": %s", resourceIdName, resourceId, description);
339+
}
340+
335341
private String pollOperation(String projectId, String operationName)
336342
throws FirebaseProjectManagementException {
337343
String url = String.format("%s/v1/%s", FIREBASE_PROJECT_MANAGEMENT_URL, operationName);
@@ -341,27 +347,29 @@ private String pollOperation(String projectId, String operationName)
341347
* Math.pow(POLL_EXPONENTIAL_BACKOFF_FACTOR, currentAttempt));
342348
sleepOrThrow(projectId, delayMillis);
343349
OperationResponse operationResponseInstance = new OperationResponse();
344-
httpHelper.makeGetRequest(url, operationResponseInstance, projectId, "Project ID");
350+
IncomingHttpResponse response = httpHelper.makeGetRequest(
351+
url, operationResponseInstance, projectId, "Project ID");
345352
if (!operationResponseInstance.done) {
346353
continue;
347354
}
348355
// The Long Running Operation API guarantees that when done == true, exactly one of 'response'
349356
// or 'error' is set.
350357
if (operationResponseInstance.response == null
351358
|| Strings.isNullOrEmpty(operationResponseInstance.response.appId)) {
352-
throw HttpHelper.createFirebaseProjectManagementException(
359+
String message = buildMessage(
353360
projectId,
354361
"Project ID",
355-
"Unable to create App: internal server error.",
356-
/* cause= */ null);
362+
"Unable to create App: internal server error.");
363+
throw new FirebaseProjectManagementException(ErrorCode.INTERNAL, message, response);
357364
}
358365
return operationResponseInstance.response.appId;
359366
}
360-
throw HttpHelper.createFirebaseProjectManagementException(
367+
368+
String message = buildMessage(
361369
projectId,
362370
"Project ID",
363-
"Unable to create App: deadline exceeded.",
364-
/* cause= */ null);
371+
"Unable to create App: deadline exceeded.");
372+
throw new FirebaseProjectManagementException(ErrorCode.DEADLINE_EXCEEDED, message, null);
365373
}
366374

367375
/**
@@ -420,19 +428,22 @@ private WaitOperationRunnable(
420428
public void run() {
421429
String url = String.format("%s/v1/%s", FIREBASE_PROJECT_MANAGEMENT_URL, operationName);
422430
OperationResponse operationResponseInstance = new OperationResponse();
431+
IncomingHttpResponse httpResponse;
423432
try {
424-
httpHelper.makeGetRequest(url, operationResponseInstance, projectId, "Project ID");
433+
httpResponse = httpHelper.makeGetRequest(
434+
url, operationResponseInstance, projectId, "Project ID");
425435
} catch (FirebaseProjectManagementException e) {
426436
settableFuture.setException(e);
427437
return;
428438
}
429439
if (!operationResponseInstance.done) {
430440
if (numberOfPreviousPolls + 1 >= MAXIMUM_POLLING_ATTEMPTS) {
431-
settableFuture.setException(HttpHelper.createFirebaseProjectManagementException(
432-
projectId,
441+
String message = buildMessage(projectId,
433442
"Project ID",
434-
"Unable to create App: deadline exceeded.",
435-
/* cause= */ null));
443+
"Unable to create App: deadline exceeded.");
444+
FirebaseProjectManagementException exception = new FirebaseProjectManagementException(
445+
ErrorCode.DEADLINE_EXCEEDED, message, httpResponse);
446+
settableFuture.setException(exception);
436447
} else {
437448
long delayMillis = (long) (
438449
POLL_BASE_WAIT_TIME_MILLIS
@@ -451,11 +462,12 @@ public void run() {
451462
// or 'error' is set.
452463
if (operationResponseInstance.response == null
453464
|| Strings.isNullOrEmpty(operationResponseInstance.response.appId)) {
454-
settableFuture.setException(HttpHelper.createFirebaseProjectManagementException(
455-
projectId,
465+
String message = buildMessage(projectId,
456466
"Project ID",
457-
"Unable to create App: internal server error.",
458-
/* cause= */ null));
467+
"Unable to create App: internal server error.");
468+
FirebaseProjectManagementException exception = new FirebaseProjectManagementException(
469+
ErrorCode.INTERNAL, message, httpResponse);
470+
settableFuture.setException(exception);
459471
} else {
460472
settableFuture.set(operationResponseInstance.response.appId);
461473
}
@@ -765,11 +777,10 @@ private void sleepOrThrow(String projectId, long delayMillis)
765777
try {
766778
sleeper.sleep(delayMillis);
767779
} catch (InterruptedException e) {
768-
throw HttpHelper.createFirebaseProjectManagementException(
769-
projectId,
780+
String message = buildMessage(projectId,
770781
"Project ID",
771-
"Unable to create App: exponential backoff interrupted.",
772-
/* cause= */ null);
782+
"Unable to create App: exponential backoff interrupted.");
783+
throw new FirebaseProjectManagementException(ErrorCode.ABORTED, message, null);
773784
}
774785
}
775786

0 commit comments

Comments
 (0)