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.
—
Structured JSON error response parsing and exception handling with detailed error information from Google API responses.
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.googleapis.json.GoogleJsonError;
import com.google.api.client.googleapis.json.GoogleJsonErrorContainer;
import com.google.api.client.json.JsonFactory;HTTP response exception that includes structured JSON error details from Google APIs.
public class GoogleJsonResponseException extends HttpResponseException {
public GoogleJsonError getDetails();
public static GoogleJsonResponseException from(JsonFactory jsonFactory, HttpResponse response)
throws IOException;
protected GoogleJsonResponseException(Builder builder, GoogleJsonError details);
public static class Builder extends HttpResponseException.Builder {
public GoogleJsonResponseException build();
public Builder setDetails(GoogleJsonError details);
public GoogleJsonError getDetails();
}
}Usage Example:
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.googleapis.json.GoogleJsonError;
try {
// Execute Google API request
MyApiResponse response = myApiClient.items().get(itemId).execute();
} catch (GoogleJsonResponseException e) {
// Handle structured JSON error
GoogleJsonError error = e.getDetails();
System.err.println("API Error: " + e.getStatusCode() + " " + e.getStatusMessage());
if (error != null) {
System.err.println("Error Code: " + error.getCode());
System.err.println("Error Message: " + error.getMessage());
// Handle specific error cases
switch (e.getStatusCode()) {
case 400:
handleBadRequest(error);
break;
case 401:
handleUnauthorized(error);
break;
case 403:
handleForbidden(error);
break;
case 404:
handleNotFound(error);
break;
case 429:
handleRateLimitExceeded(error);
break;
case 500:
handleInternalServerError(error);
break;
default:
handleGenericError(error);
}
}
} catch (IOException e) {
// Handle general I/O errors
System.err.println("Network error: " + e.getMessage());
}Represents detailed error information from Google JSON API responses.
public final class GoogleJsonError extends GenericJson {
public Integer getCode();
public GoogleJsonError setCode(Integer code);
public String getMessage();
public GoogleJsonError setMessage(String message);
public List<ErrorInfo> getErrors();
public GoogleJsonError setErrors(List<ErrorInfo> errors);
public static final class ErrorInfo extends GenericJson {
public String getDomain();
public ErrorInfo setDomain(String domain);
public String getReason();
public ErrorInfo setReason(String reason);
public String getMessage();
public ErrorInfo setMessage(String message);
public String getLocation();
public ErrorInfo setLocation(String location);
public String getLocationType();
public ErrorInfo setLocationType(String locationType);
public String getExtendedHelp();
public ErrorInfo setExtendedHelp(String extendedHelp);
public String getSendReport();
public ErrorInfo setSendReport(String sendReport);
}
}Container for Google JSON errors, used in batch operations and some API responses.
public class GoogleJsonErrorContainer extends GenericJson {
public GoogleJsonError getError();
public GoogleJsonErrorContainer setError(GoogleJsonError error);
}Usage Example:
import com.google.api.client.googleapis.json.GoogleJsonError;
// Detailed error handling
private void handleDetailedError(GoogleJsonError error) {
System.err.println("Main Error: " + error.getCode() + " - " + error.getMessage());
// Process individual error details
if (error.getErrors() != null) {
for (GoogleJsonError.ErrorInfo errorInfo : error.getErrors()) {
System.err.println("Error Detail:");
System.err.println(" Domain: " + errorInfo.getDomain());
System.err.println(" Reason: " + errorInfo.getReason());
System.err.println(" Message: " + errorInfo.getMessage());
if (errorInfo.getLocation() != null) {
System.err.println(" Location: " + errorInfo.getLocation() +
" (" + errorInfo.getLocationType() + ")");
}
if (errorInfo.getExtendedHelp() != null) {
System.err.println(" Help: " + errorInfo.getExtendedHelp());
}
}
}
}// Handle validation errors
private void handleBadRequest(GoogleJsonError error) {
System.err.println("Validation Error: " + error.getMessage());
if (error.getErrors() != null) {
for (GoogleJsonError.ErrorInfo errorInfo : error.getErrors()) {
if ("invalid".equals(errorInfo.getReason())) {
System.err.println("Invalid field: " + errorInfo.getLocation());
} else if ("required".equals(errorInfo.getReason())) {
System.err.println("Missing required field: " + errorInfo.getLocation());
}
}
}
}
// Handle authentication errors
private void handleUnauthorized(GoogleJsonError error) {
System.err.println("Authentication failed: " + error.getMessage());
// Trigger token refresh or re-authentication
refreshAuthenticationToken();
}
// Handle permission errors
private void handleForbidden(GoogleJsonError error) {
System.err.println("Access forbidden: " + error.getMessage());
if (error.getErrors() != null) {
for (GoogleJsonError.ErrorInfo errorInfo : error.getErrors()) {
if ("insufficientPermissions".equals(errorInfo.getReason())) {
System.err.println("Missing permission: " + errorInfo.getMessage());
}
}
}
}
// Handle rate limiting
private void handleRateLimitExceeded(GoogleJsonError error) {
System.err.println("Rate limit exceeded: " + error.getMessage());
// Implement exponential backoff
try {
Thread.sleep(calculateRetryDelay());
// Retry the request
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}public <T> T executeWithRetry(AbstractGoogleClientRequest<T> request, int maxRetries)
throws IOException {
int attempt = 0;
while (attempt < maxRetries) {
try {
return request.execute();
} catch (GoogleJsonResponseException e) {
attempt++;
// Determine if error is retryable
if (!isRetryableError(e) || attempt >= maxRetries) {
throw e;
}
// Calculate delay based on error type
long delay = calculateRetryDelay(e, attempt);
try {
Thread.sleep(delay);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new IOException("Interrupted during retry", ie);
}
}
}
throw new IOException("Maximum retries exceeded");
}
private boolean isRetryableError(GoogleJsonResponseException e) {
int statusCode = e.getStatusCode();
// Retryable HTTP status codes
if (statusCode == 429 || statusCode >= 500) {
return true;
}
// Check for specific retryable error reasons
GoogleJsonError error = e.getDetails();
if (error != null && error.getErrors() != null) {
for (GoogleJsonError.ErrorInfo errorInfo : error.getErrors()) {
String reason = errorInfo.getReason();
if ("rateLimitExceeded".equals(reason) ||
"userRateLimitExceeded".equals(reason) ||
"backendError".equals(reason)) {
return true;
}
}
}
return false;
}
private long calculateRetryDelay(GoogleJsonResponseException e, int attempt) {
// Base exponential backoff: 2^attempt * 1000ms
long baseDelay = (long) Math.pow(2, attempt) * 1000;
// Cap at 60 seconds
baseDelay = Math.min(baseDelay, 60000);
// Add jitter to prevent thundering herd
long jitter = (long) (Math.random() * 1000);
return baseDelay + jitter;
}import java.util.logging.Logger;
import java.util.logging.Level;
private static final Logger logger = Logger.getLogger(MyApiClient.class.getName());
private void logApiError(GoogleJsonResponseException e) {
GoogleJsonError error = e.getDetails();
// Create structured log entry
StringBuilder logMessage = new StringBuilder();
logMessage.append("Google API Error - ");
logMessage.append("Status: ").append(e.getStatusCode()).append(" ");
logMessage.append("Message: ").append(e.getStatusMessage()).append(" ");
if (error != null) {
logMessage.append("Code: ").append(error.getCode()).append(" ");
logMessage.append("Details: ").append(error.getMessage());
if (error.getErrors() != null) {
logMessage.append(" Errors: [");
for (GoogleJsonError.ErrorInfo errorInfo : error.getErrors()) {
logMessage.append(errorInfo.getDomain())
.append("/")
.append(errorInfo.getReason())
.append(": ")
.append(errorInfo.getMessage())
.append("; ");
}
logMessage.append("]");
}
}
logger.log(Level.WARNING, logMessage.toString(), e);
}// Example error metrics collection
public class ApiErrorMetrics {
private final Map<Integer, AtomicLong> statusCodeCounts = new ConcurrentHashMap<>();
private final Map<String, AtomicLong> errorReasonCounts = new ConcurrentHashMap<>();
public void recordError(GoogleJsonResponseException e) {
// Count by status code
statusCodeCounts.computeIfAbsent(e.getStatusCode(), k -> new AtomicLong(0))
.incrementAndGet();
// Count by error reason
GoogleJsonError error = e.getDetails();
if (error != null && error.getErrors() != null) {
for (GoogleJsonError.ErrorInfo errorInfo : error.getErrors()) {
String reason = errorInfo.getReason();
if (reason != null) {
errorReasonCounts.computeIfAbsent(reason, k -> new AtomicLong(0))
.incrementAndGet();
}
}
}
}
public void printMetrics() {
System.out.println("API Error Metrics:");
System.out.println("Status Codes:");
statusCodeCounts.forEach((code, count) ->
System.out.println(" " + code + ": " + count.get()));
System.out.println("Error Reasons:");
errorReasonCounts.forEach((reason, count) ->
System.out.println(" " + reason + ": " + count.get()));
}
}Base HTTP response exception class.
HTTP response representation.
JSON factory for parsing JSON content.
Base class for JSON data models.
Exception for I/O operations.
Java list interface for collections.
Java integer wrapper class.
Java string class.
Java logging utility.
Java map interface for key-value collections.
Thread-safe long counter for metrics.
Install with Tessl CLI
npx tessl i tessl/maven-com-google-api-client--google-api-client