This guide outlines how to customize several of the more advanced aspects of the
Java client library. A common pattern is that many of these features rely on the
underlying Callable
rather than the standard methods. The callable is
generally a good place to look for other per-RPC features that aren't documented
here.
Timeout
The Java library provides a surface for setting timeouts on a per-call level.
The default value is set based on the method_config/timeout
setting in
googleads_grpc_service_config.json.
Set a lower value if you need to enforce a shorter limit on the maximum time for
an API call.
To use this feature you should use the callable object directly. For example, if
calling GoogleAdsService.searchStream()
, the timeout would be set as:
try (GoogleAdsServiceClient googleAdsServiceClient =
googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
// Constructs the SearchGoogleAdsStreamRequest.
SearchGoogleAdsStreamRequest request = ...
// Executes the API call, with a timeout of 5 minutes.
ServerStream<SearchGoogleAdsStreamResponse> result = googleAdsServiceClient
.searchStreamCallable()
.call(request,
GrpcCallContext.createDefault().withTimeout(Duration.of(5, ChronoUnit.MINUTES)));
}
You can set the timeout to 2 hours or more, but the API may still time out
extremely long-running requests and return a
DEADLINE_EXCEEDED
error.
If this becomes an issue, it is usually best to split the query up and
execute the chunks in parallel; this avoids the situation where a long
running request fails and the only way to recover is to trigger the request
again from the start.
Retry settings
The Java library also provides a surface for configuring retry settings on a
per-call level. To use this feature you should use the callable object directly.
For example, if calling GoogleAdsService.searchStream()
, the retry settings
would be configured as follows:
// Creates a context object with the custom retry settings.
GrpcCallContext context = GrpcCallContext.createDefault()
.withRetrySettings(RetrySettings.newBuilder()
.setInitialRetryDelay(Duration.ofMillis(10L))
.setMaxRetryDelay(Duration.ofSeconds(10L))
.setRetryDelayMultiplier(1.4)
.setMaxAttempts(10)
.setLogicalTimeout(Duration.ofSeconds(30L))
.build());
// Creates and issues a search Google Ads stream request.
ServerStream<SearchGoogleAdsStreamResponse> stream =
googleAdsServiceClient.searchStreamCallable().call(request, context);
Startup time performance optimization
You may notice a small delay the first time a GoogleAdsClient
instance is
created. This is due to the fluent interface for services
(GoogleAdsClient.getVersionXX()
), which loads all the API classes at
once in order to provide a more convenient mechanism for constructing
service classes.
If the first request performance is in the critical path for your application, you should follow these steps:
Create the
GoogleAdsClient
on startup, before serving user requests.Send a few warm-up requests to the Google Ads API when the process first starts. For example:
// Runs some warm-up requests. try (GoogleAdsServiceClient googleAdsServiceClient = googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) { // Runs 5 warm-up requests. In our profiling we see that 90% of performance // loss is only experienced on the first API call. After 3 subsequent calls we // saw a negligible improvement in performance. for (int i = 0; i < 5; ++i) { // Warm-up queries are run with a nonexistent CID so the calls will fail. If // you have a CID that you know will be accessible with the OAuth // credentials provided you may want to provide that instead and avoid the // try-catch. try { googleAdsServiceClient.search("-1", "Warm-up query"); } catch (GoogleAdsException ex) { // Do nothing, we're expecting this to fail. } } }
The warm-up requests only need to be run once per process. Every subsequent service client creation will automatically reuse the preloaded classes.
Service client reuse
You should reuse service client instances where practical since each call to
GoogleAdsClient.getVersionXXX().createYYYServiceClient()
will create a new
TCP connection.
You must make sure that you close the client when it's no longer required. This
can be done in a
try-with-resources
block or by calling close()
on the service client.
If you attempt to use a closed service client to make API requests, the service
client method will throw a java.util.concurrent.RejectedExecutionException
.
App engine fails to deploy if JAR > 32 MB
App Engine has a quota of 32 MB for each uploaded file. The JAR for google-ads
will be considerably bigger than this, even moreso using shade/shadow jar
deployments. If you deploy jars by hand, you might get errors like:
ERROR: (gcloud.app.deploy) Cannot upload file [<your-app>/WEB-INF/lib/google-ads-34.0.0.jar],
which has size [66095767] (greater than maximum allowed size of [33554432])
Instead, deploy using the AppEngine
Gradle plugin
or
Maven plugin.
Each has an option for enableJarSplitting
which will split each jar into 10 MB
chunks and upload those instead.
Shadow dependencies
If your project has dependencies that conflict with the library's, you should inspect your project's dependencies using one of the following commands, then modify your project's dependencies as needed.
Maven
mvn dependency:tree
Gradle
./gradlew dependencies
If resolving dependency conflicts is infeasible, you can depend on the shaded version of the library instead.
Maven
<dependency> <groupId>com.google.api-ads</groupId> <artifactId>google-ads-shadowjar</artifactId> <version>34.0.0</version> </dependency>
Gradle
implementation 'com.google.api-ads:google-ads-shadowjar:34.0.0'