diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/errorhandling/HandlePartialFailure.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/errorhandling/HandlePartialFailure.java index 7d2e350780..2db2aaf2d6 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/errorhandling/HandlePartialFailure.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/errorhandling/HandlePartialFailure.java @@ -22,6 +22,7 @@ import com.google.ads.googleads.lib.GoogleAdsClient; import com.google.ads.googleads.v8.errors.GoogleAdsError; import com.google.ads.googleads.v8.errors.GoogleAdsException; +import com.google.ads.googleads.v8.errors.GoogleAdsFailure; import com.google.ads.googleads.v8.resources.AdGroup; import com.google.ads.googleads.v8.services.AdGroupOperation; import com.google.ads.googleads.v8.services.AdGroupServiceClient; @@ -30,7 +31,6 @@ import com.google.ads.googleads.v8.services.MutateAdGroupsResponse; import com.google.ads.googleads.v8.utils.ErrorUtils; import com.google.ads.googleads.v8.utils.ResourceNames; -import com.google.protobuf.InvalidProtocolBufferException; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Arrays; @@ -57,7 +57,7 @@ private static class HandlePartialFailureParams extends CodeSampleParams { private Long campaignId; } - public static void main(String[] args) throws InvalidProtocolBufferException { + public static void main(String[] args) { HandlePartialFailureParams params = new HandlePartialFailureParams(); if (!params.parseArguments(args)) { // Either pass the required parameters for this example on the command line, or insert them @@ -96,8 +96,7 @@ public static void main(String[] args) throws InvalidProtocolBufferException { } /** Runs the example. */ - public void runExample(GoogleAdsClient googleAdsClient, long customerId, long campaignId) - throws InvalidProtocolBufferException { + public void runExample(GoogleAdsClient googleAdsClient, long customerId, long campaignId) { MutateAdGroupsResponse response = createAdGroups(googleAdsClient, customerId, campaignId); // Checks for existence of any partial failures in the response. @@ -165,15 +164,18 @@ private boolean checkIfPartialFailureErrorExists(MutateAdGroupsResponse response /** Displays the result from the mutate operation. */ // [START handle_partial_failure_2] - private void printResults(MutateAdGroupsResponse response) throws InvalidProtocolBufferException { + private void printResults(MutateAdGroupsResponse response) { int operationIndex = 0; for (MutateAdGroupResult result : response.getResultsList()) { if (ErrorUtils.getInstance().isPartialFailureResult(result)) { // May throw on this line. Most likely this means the wrong version of the ErrorUtils // class has been used. + GoogleAdsFailure googleAdsFailure = ErrorUtils.getInstance() + .getGoogleAdsFailure(response.getPartialFailureError()); + for (GoogleAdsError error : ErrorUtils.getInstance() - .getGoogleAdsErrors(operationIndex, response.getPartialFailureError())) { + .getGoogleAdsErrors(operationIndex, googleAdsFailure)) { System.out.printf("Operation %d failed with error: %s%n", operationIndex, error); } } else { diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/AddCustomerMatchUserList.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/AddCustomerMatchUserList.java index bd8d8e609e..967351df62 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/AddCustomerMatchUserList.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/AddCustomerMatchUserList.java @@ -30,6 +30,7 @@ import com.google.ads.googleads.v8.enums.OfflineUserDataJobTypeEnum.OfflineUserDataJobType; import com.google.ads.googleads.v8.errors.GoogleAdsError; import com.google.ads.googleads.v8.errors.GoogleAdsException; +import com.google.ads.googleads.v8.errors.GoogleAdsFailure; import com.google.ads.googleads.v8.resources.OfflineUserDataJob; import com.google.ads.googleads.v8.resources.UserList; import com.google.ads.googleads.v8.services.AddOfflineUserDataJobOperationsRequest; @@ -44,6 +45,7 @@ import com.google.ads.googleads.v8.services.SearchGoogleAdsStreamResponse; import com.google.ads.googleads.v8.services.UserListOperation; import com.google.ads.googleads.v8.services.UserListServiceClient; +import com.google.ads.googleads.v8.utils.ErrorUtils; import com.google.api.gax.rpc.ServerStream; import com.google.common.collect.ImmutableList; import java.io.FileNotFoundException; @@ -219,11 +221,13 @@ private void addUsersToCustomerMatchUserList( // NOTE: The details of each partial failure error are not printed here, you can refer to // the example HandlePartialFailure.java to learn more. if (response.hasPartialFailureError()) { + GoogleAdsFailure googleAdsFailure = + ErrorUtils.getInstance().getGoogleAdsFailure(response.getPartialFailureError()); System.out.printf( "Encountered %d partial failure errors while adding %d operations to the offline user " + "data job: '%s'. Only the successfully added operations will be executed when " + "the job runs.%n", - response.getPartialFailureError().getDetailsCount(), + googleAdsFailure.getErrorsCount(), userDataJobOperations.size(), response.getPartialFailureError().getMessage()); } else { diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadCallConversion.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadCallConversion.java index 5a1b9d38fb..daec66a49a 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadCallConversion.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadCallConversion.java @@ -20,12 +20,14 @@ import com.google.ads.googleads.lib.GoogleAdsClient; import com.google.ads.googleads.v8.errors.GoogleAdsError; import com.google.ads.googleads.v8.errors.GoogleAdsException; +import com.google.ads.googleads.v8.errors.GoogleAdsFailure; import com.google.ads.googleads.v8.services.CallConversion; import com.google.ads.googleads.v8.services.CallConversionResult; import com.google.ads.googleads.v8.services.ConversionUploadServiceClient; import com.google.ads.googleads.v8.services.CustomVariable; import com.google.ads.googleads.v8.services.UploadCallConversionsRequest; import com.google.ads.googleads.v8.services.UploadCallConversionsResponse; +import com.google.ads.googleads.v8.utils.ErrorUtils; import com.google.ads.googleads.v8.utils.ResourceNames; import java.io.FileNotFoundException; import java.io.IOException; @@ -185,6 +187,11 @@ private void runExample( // Prints any partial failure errors returned. if (response.hasPartialFailureError()) { + GoogleAdsFailure googleAdsFailure = + ErrorUtils.getInstance().getGoogleAdsFailure(response.getPartialFailureError()); + googleAdsFailure + .getErrorsList() + .forEach(e -> System.out.println("Partial failure occurred: " + e.getMessage())); throw new RuntimeException( "Partial failure occurred " + response.getPartialFailureError().getMessage()); } diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadConversionAdjustment.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadConversionAdjustment.java index d0dc90f3d5..993fc7033f 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadConversionAdjustment.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadConversionAdjustment.java @@ -21,6 +21,7 @@ import com.google.ads.googleads.v8.enums.ConversionAdjustmentTypeEnum.ConversionAdjustmentType; import com.google.ads.googleads.v8.errors.GoogleAdsError; import com.google.ads.googleads.v8.errors.GoogleAdsException; +import com.google.ads.googleads.v8.errors.GoogleAdsFailure; import com.google.ads.googleads.v8.services.ConversionAdjustment; import com.google.ads.googleads.v8.services.ConversionAdjustmentResult; import com.google.ads.googleads.v8.services.ConversionAdjustmentUploadServiceClient; @@ -28,6 +29,7 @@ import com.google.ads.googleads.v8.services.RestatementValue; import com.google.ads.googleads.v8.services.UploadConversionAdjustmentsRequest; import com.google.ads.googleads.v8.services.UploadConversionAdjustmentsResponse; +import com.google.ads.googleads.v8.utils.ErrorUtils; import com.google.ads.googleads.v8.utils.ResourceNames; import java.io.FileNotFoundException; import java.io.IOException; @@ -203,8 +205,11 @@ private void runExample( // Prints any partial errors returned. if (response.hasPartialFailureError()) { - System.out.printf( - "Partial error encountered: '%s'.%n", response.getPartialFailureError().getMessage()); + GoogleAdsFailure googleAdsFailure = + ErrorUtils.getInstance().getGoogleAdsFailure(response.getPartialFailureError()); + googleAdsFailure + .getErrorsList() + .forEach(e -> System.out.println("Partial failure occurred: " + e.getMessage())); } else { // Prints the result. ConversionAdjustmentResult result = response.getResults(0); diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadOfflineConversion.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadOfflineConversion.java index 534da23b7f..150bc41a6d 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadOfflineConversion.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadOfflineConversion.java @@ -20,12 +20,14 @@ import com.google.ads.googleads.lib.GoogleAdsClient; import com.google.ads.googleads.v8.errors.GoogleAdsError; import com.google.ads.googleads.v8.errors.GoogleAdsException; +import com.google.ads.googleads.v8.errors.GoogleAdsFailure; import com.google.ads.googleads.v8.services.ClickConversion; import com.google.ads.googleads.v8.services.ClickConversionResult; import com.google.ads.googleads.v8.services.ConversionUploadServiceClient; import com.google.ads.googleads.v8.services.CustomVariable; import com.google.ads.googleads.v8.services.UploadClickConversionsRequest; import com.google.ads.googleads.v8.services.UploadClickConversionsResponse; +import com.google.ads.googleads.v8.utils.ErrorUtils; import com.google.ads.googleads.v8.utils.ResourceNames; import java.io.FileNotFoundException; import java.io.IOException; @@ -182,8 +184,11 @@ private void runExample( // Prints any partial errors returned. if (response.hasPartialFailureError()) { - System.out.printf( - "Partial error encountered: '%s'.%n", response.getPartialFailureError().getMessage()); + GoogleAdsFailure googleAdsFailure = + ErrorUtils.getInstance().getGoogleAdsFailure(response.getPartialFailureError()); + googleAdsFailure + .getErrorsList() + .forEach(e -> System.out.println("Partial failure occurred: " + e.getMessage())); } // Prints the result. diff --git a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadStoreSalesTransactions.java b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadStoreSalesTransactions.java index 855c84f309..aaee8be216 100644 --- a/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadStoreSalesTransactions.java +++ b/google-ads-examples/src/main/java/com/google/ads/googleads/examples/remarketing/UploadStoreSalesTransactions.java @@ -28,6 +28,7 @@ import com.google.ads.googleads.v8.enums.OfflineUserDataJobTypeEnum.OfflineUserDataJobType; import com.google.ads.googleads.v8.errors.GoogleAdsError; import com.google.ads.googleads.v8.errors.GoogleAdsException; +import com.google.ads.googleads.v8.errors.GoogleAdsFailure; import com.google.ads.googleads.v8.resources.OfflineUserDataJob; import com.google.ads.googleads.v8.services.AddOfflineUserDataJobOperationsRequest; import com.google.ads.googleads.v8.services.AddOfflineUserDataJobOperationsResponse; @@ -36,6 +37,7 @@ import com.google.ads.googleads.v8.services.GoogleAdsServiceClient; import com.google.ads.googleads.v8.services.OfflineUserDataJobOperation; import com.google.ads.googleads.v8.services.OfflineUserDataJobServiceClient; +import com.google.ads.googleads.v8.utils.ErrorUtils; import com.google.ads.googleads.v8.utils.ResourceNames; import com.google.common.collect.ImmutableList; import java.io.FileNotFoundException; @@ -469,11 +471,16 @@ private void addTransactionsToOfflineUserDataJob( // NOTE: The details of each partial failure error are not printed here, you can refer to // the example HandlePartialFailure.java to learn more. if (response.hasPartialFailureError()) { + GoogleAdsFailure googleAdsFailure = + ErrorUtils.getInstance().getGoogleAdsFailure(response.getPartialFailureError()); + googleAdsFailure + .getErrorsList() + .forEach(e -> System.out.println("Partial failure occurred: " + e.getMessage())); System.out.printf( "Encountered %d partial failure errors while adding %d operations to the offline user " + "data job: '%s'. Only the successfully added operations will be executed when " + "the job runs.%n", - response.getPartialFailureError().getDetailsCount(), + ErrorUtils.getInstance().getFailedOperationIndices(googleAdsFailure).size(), userDataJobOperations.size(), response.getPartialFailureError().getMessage()); } else { diff --git a/google-ads/build.gradle b/google-ads/build.gradle index 65e6824842..e5961fd94e 100644 --- a/google-ads/build.gradle +++ b/google-ads/build.gradle @@ -49,6 +49,7 @@ sourceSets { runtimeClasspath += sourceSets.main.output } } +sourceSets.test.java.srcDir new File(buildDir, 'generated/source/proto/test') protobuf { protoc { diff --git a/google-ads/src/main/java/com/google/ads/googleads/lib/utils/AbstractErrorUtils.java b/google-ads/src/main/java/com/google/ads/googleads/lib/utils/AbstractErrorUtils.java index e1dab0c56c..66ed48cf0a 100644 --- a/google-ads/src/main/java/com/google/ads/googleads/lib/utils/AbstractErrorUtils.java +++ b/google-ads/src/main/java/com/google/ads/googleads/lib/utils/AbstractErrorUtils.java @@ -21,6 +21,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; /** Contains utility methods for handling partial failure of operations. */ public abstract class AbstractErrorUtils< @@ -77,9 +79,9 @@ public abstract class AbstractErrorUtils< * empty list otherwise. * *
This method supports The status object contains a details repeated field. This contains at most 1 Any protos
+ * which encode a GoogleAdsFailure instance.
+ *
+ * @param partialFailureStatus the partial failure Status object returned in the repsponse.
+ * @return the GoogleAdsFailure instance describing the partial failures, or null if none is
+ * found.
+ * @throws DeserializeException if an {@link InvalidProtocolBufferException} is encountered.
+ * @throws NullPointerException if partialFailureStatus is null.
+ */
+ public GoogleAdsFailureT getGoogleAdsFailure(Status partialFailureStatus) {
+ return partialFailureStatus.getDetailsCount() == 0
+ ? null
+ : getGoogleAdsFailure(partialFailureStatus.getDetails(0));
}
/** Checks if a result in a mutate response is a partial failure. */
@@ -192,8 +227,7 @@ protected static class ErrorPathXXXService.mutate(request) where the request contains a
- * list of operations named "operations". It also supports
- * GoogleAdsService.mutateGoogleAds(request), where the request contains a list of
- * MutateOperations named "mutate_operations".
+ * list of operations named "operations". It also supports
+ * GoogleAdsService.mutateGoogleAds(request), where the request contains a list of
+ * MutateOperations named "mutate_operations".
*
* @param operationIndex the index of the operation, starting from 0.
* @param partialFailureStatus a partialFailure status, with the detail list containing {@link
@@ -108,8 +110,7 @@ public ListErrorUtils
- * being used.
+ * @throws DeserializeException if an {@link InvalidProtocolBufferException} is encountered. This
+ * would indicate that the detail object was not-null, but the contents couldn't be
+ * deserialized to the target type. This may indicate that the target type is incorrect, or
+ * that the content of the Any message is incorrect.
+ * @throws NullPointerException if detail is null.
*/
- public GoogleAdsFailureT getGoogleAdsFailure(Any detail) throws InvalidProtocolBufferException {
- return detail.unpack(getGoogleAdsFailureClass());
+ public GoogleAdsFailureT getGoogleAdsFailure(Any detail) {
+ try {
+ return detail.unpack(getGoogleAdsFailureClass());
+ } catch (InvalidProtocolBufferException e) {
+ throw new DeserializeException(e);
+ }
+ }
+
+ /**
+ * Unpacks the GoogleAdsFailureT instance form a partial failure status object.
+ *
+ *