The Google APIs Client Library for Java is a flexible, efficient, and powerful Java client library for accessing any HTTP-based API on the web, not just Google APIs.
—
Efficient batch request processing to combine multiple API calls into a single HTTP request, reducing network overhead and improving performance.
import com.google.api.client.googleapis.batch.BatchRequest;
import com.google.api.client.googleapis.batch.BatchCallback;
import com.google.api.client.googleapis.batch.json.JsonBatchCallback;
import com.google.api.client.googleapis.batch.BatchUnparsedResponse;
import com.google.api.client.googleapis.batch.HttpRequestContent;Container for multiple HTTP requests to be executed as a single batch operation.
public final class BatchRequest {
public BatchRequest(HttpTransport transport, HttpRequestInitializer httpRequestInitializer);
public <T, E> BatchRequest queue(HttpRequest request, Class<T> dataClass, Class<E> errorClass,
BatchCallback<T, E> callback) throws IOException;
public <T, E> BatchRequest queue(AbstractGoogleClientRequest<T> request, Class<T> dataClass,
Class<E> errorClass, BatchCallback<T, E> callback) throws IOException;
public void execute() throws IOException;
public int size();
public BatchRequest setSleeper(Sleeper sleeper);
public Sleeper getSleeper();
}Usage Example:
import com.google.api.client.googleapis.batch.BatchRequest;
import com.google.api.client.googleapis.batch.BatchCallback;
import com.google.api.client.http.HttpHeaders;
// Create batch request
BatchRequest batch = new BatchRequest(transport, credential);
// Define callback for handling responses
BatchCallback<MyResource, GoogleJsonError> callback = new BatchCallback<MyResource, GoogleJsonError>() {
@Override
public void onSuccess(MyResource resource, HttpHeaders responseHeaders) throws IOException {
System.out.println("Successfully processed: " + resource.getId());
}
@Override
public void onFailure(GoogleJsonError error, HttpHeaders responseHeaders) throws IOException {
System.err.println("Error: " + error.getMessage());
}
};
// Queue multiple requests
for (String itemId : itemIds) {
MyApiRequest request = myApiClient.items().get(itemId);
batch.queue(request, MyResource.class, GoogleJsonError.class, callback);
}
// Execute all requests as a single batch
batch.execute();Interface for handling batch request responses.
public interface BatchCallback<T, E> {
void onSuccess(T t, HttpHeaders responseHeaders) throws IOException;
void onFailure(E e, HttpHeaders responseHeaders) throws IOException;
}JSON-specific batch callback implementation.
public abstract class JsonBatchCallback<T> implements BatchCallback<T, GoogleJsonError> {
public abstract void onSuccess(T t, HttpHeaders responseHeaders) throws IOException;
public abstract void onFailure(GoogleJsonError e, HttpHeaders responseHeaders) throws IOException;
}Usage Example:
import com.google.api.client.googleapis.batch.json.JsonBatchCallback;
import com.google.api.client.googleapis.json.GoogleJsonError;
// Use JsonBatchCallback for simplified JSON error handling
JsonBatchCallback<MyResource> jsonCallback = new JsonBatchCallback<MyResource>() {
@Override
public void onSuccess(MyResource resource, HttpHeaders responseHeaders) throws IOException {
System.out.println("Resource created: " + resource.getName());
System.out.println("ETag: " + responseHeaders.getETag());
}
@Override
public void onFailure(GoogleJsonError error, HttpHeaders responseHeaders) throws IOException {
System.err.println("Request failed with code: " + error.getCode());
System.err.println("Error message: " + error.getMessage());
if (error.getErrors() != null) {
for (GoogleJsonError.ErrorInfo errorInfo : error.getErrors()) {
System.err.println(" - " + errorInfo.getReason() + ": " + errorInfo.getMessage());
}
}
}
};
// Queue request with JSON callback
batch.queue(createRequest, MyResource.class, GoogleJsonError.class, jsonCallback);// Custom callback with detailed response handling
BatchCallback<MyResource, GoogleJsonError> detailedCallback = new BatchCallback<MyResource, GoogleJsonError>() {
@Override
public void onSuccess(MyResource resource, HttpHeaders responseHeaders) throws IOException {
// Process successful response
String requestId = responseHeaders.getFirst("X-Request-Id");
long rateLimitRemaining = Long.parseLong(responseHeaders.getFirst("X-RateLimit-Remaining"));
System.out.println("Request ID: " + requestId);
System.out.println("Rate limit remaining: " + rateLimitRemaining);
// Handle the resource data
processResource(resource);
}
@Override
public void onFailure(GoogleJsonError error, HttpHeaders responseHeaders) throws IOException {
// Handle different types of errors
switch (error.getCode()) {
case 404:
System.err.println("Resource not found: " + error.getMessage());
break;
case 403:
System.err.println("Permission denied: " + error.getMessage());
break;
case 429:
System.err.println("Rate limit exceeded, retry after: " +
responseHeaders.getRetryAfter());
break;
default:
System.err.println("Unexpected error: " + error.getMessage());
}
}
};import java.util.List;
import java.util.ArrayList;
// Process large number of requests in manageable batches
public void processBatchesInChunks(List<String> itemIds, int batchSize) throws IOException {
List<List<String>> chunks = partition(itemIds, batchSize);
for (List<String> chunk : chunks) {
BatchRequest batch = new BatchRequest(transport, credential);
for (String itemId : chunk) {
MyApiRequest request = myApiClient.items().get(itemId);
batch.queue(request, MyResource.class, GoogleJsonError.class, callback);
}
System.out.println("Executing batch of " + batch.size() + " requests");
batch.execute();
// Optional delay between batches to respect rate limits
Thread.sleep(1000);
}
}
private <T> List<List<T>> partition(List<T> list, int size) {
List<List<T>> chunks = new ArrayList<>();
for (int i = 0; i < list.size(); i += size) {
chunks.add(list.subList(i, Math.min(i + size, list.size())));
}
return chunks;
}Represents an unparsed response within a batch operation.
public class BatchUnparsedResponse {
public String getContentId();
public int getStatusCode();
public String getReasonPhrase();
public HttpHeaders getHeaders();
public InputStream getContent();
}Represents HTTP request content for batch operations.
public class HttpRequestContent implements HttpContent {
public HttpRequestContent(HttpRequest request);
public long getLength() throws IOException;
public String getType();
public boolean retrySupported();
public void writeTo(OutputStream out) throws IOException;
}// Callback that tracks both successes and failures
public class BatchTrackingCallback implements BatchCallback<MyResource, GoogleJsonError> {
private final AtomicInteger successCount = new AtomicInteger(0);
private final AtomicInteger failureCount = new AtomicInteger(0);
private final List<String> errors = new ArrayList<>();
@Override
public void onSuccess(MyResource resource, HttpHeaders responseHeaders) throws IOException {
successCount.incrementAndGet();
// Process successful resource
}
@Override
public void onFailure(GoogleJsonError error, HttpHeaders responseHeaders) throws IOException {
failureCount.incrementAndGet();
errors.add("Error " + error.getCode() + ": " + error.getMessage());
}
public void printSummary() {
System.out.println("Batch completed: " + successCount.get() + " successes, " +
failureCount.get() + " failures");
if (!errors.isEmpty()) {
System.out.println("Errors:");
errors.forEach(System.out::println);
}
}
}public void executeWithRetry(BatchRequest batch, int maxRetries) throws IOException {
int attempt = 0;
while (attempt < maxRetries) {
try {
batch.execute();
return; // Success
} catch (IOException e) {
attempt++;
if (attempt >= maxRetries) {
throw e; // Final attempt failed
}
// Exponential backoff
try {
Thread.sleep(Math.min(1000 * (1L << attempt), 30000)); // Max 30 seconds
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new IOException("Interrupted during retry", ie);
}
}
}
}// Recommended batch sizes for different operations
public static final int OPTIMAL_READ_BATCH_SIZE = 100;
public static final int OPTIMAL_WRITE_BATCH_SIZE = 50;
public static final int MAX_BATCH_SIZE = 1000; // Google API limit
// Adjust batch size based on operation type
public BatchRequest createOptimalBatch(String operationType) {
BatchRequest batch = new BatchRequest(transport, credential);
// Configure batch based on operation type
switch (operationType) {
case "read":
// Larger batches for read operations
return batch;
case "write":
// Smaller batches for write operations to handle errors better
return batch;
default:
return batch;
}
}HTTP transport interface for network communication.
Interface for initializing HTTP requests.
HTTP request representation.
HTTP headers container.
Base class for Google API client requests.
Google JSON error response representation.
Java input stream for reading response content.
Java output stream for writing request content.
Exception for I/O operations.
Interface for controlling sleep behavior during batch operations.
Java class type parameter for response type specification.
Thread-safe integer for counting operations in concurrent scenarios.
Install with Tessl CLI
npx tessl i tessl/maven-com-google-api-client--google-api-client