CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-google-api--api-common

Common utilities for Google APIs in Java

Pending
Overview
Eval results
Files

core-api.mddocs/

Core API

The core API provides fundamental asynchronous programming utilities, service lifecycle management, and functional interfaces that form the foundation for Google API client libraries.

Capabilities

ApiFuture Interface

A future that supports adding listeners, similar to Guava's ListenableFuture. This is the primary async result type used throughout Google API libraries.

/**
 * A future that can have listeners added to be called when the computation completes
 * @param <V> The result type returned by this Future's get method
 */
interface ApiFuture<V> extends Future<V> {
    /**
     * Registers a listener to be run on the given executor
     * @param listener The listener to run when the computation is complete
     * @param executor The executor to run the listener in
     */
    void addListener(Runnable listener, Executor executor);
}

ApiFutures Utility Class

Static utility methods for working with ApiFuture instances, providing transformation, combination, and creation operations.

/**
 * Static utility methods for ApiFuture instances
 */
class ApiFutures {
    /**
     * Registers a callback to be run when the given ApiFuture completes
     * @param future The future to attach the callback to
     * @param callback The callback to execute on completion
     * @param executor The executor to run the callback in
     */
    static <V> void addCallback(
        ApiFuture<V> future, 
        ApiFutureCallback<? super V> callback, 
        Executor executor
    );
    
    /**
     * Creates an ApiFuture which has its value set immediately upon construction
     * @param value The value to set
     * @return A future with the given value
     */
    static <V> ApiFuture<V> immediateFuture(V value);
    
    /**
     * Creates an ApiFuture which has an exception set immediately upon construction
     * @param throwable The exception to set
     * @return A future with the given exception
     */
    static <V> ApiFuture<V> immediateFailedFuture(Throwable throwable);
    
    /**
     * Creates an ApiFuture which is cancelled immediately upon construction
     * @return A cancelled future
     */
    static <V> ApiFuture<V> immediateCancelledFuture();
    
    /**
     * Returns a new ApiFuture whose result is the product of applying the given Function to the result of the given ApiFuture
     * @param input The future to transform
     * @param function The function to apply to the input future's result
     * @param executor The executor to run the transformation in
     * @return A future with the transformed result
     */
    static <I, O> ApiFuture<O> transform(
        ApiFuture<? extends I> input, 
        ApiFunction<? super I, ? extends O> function, 
        Executor executor
    );
    
    /**
     * Returns a new ApiFuture whose result is asynchronously derived from the result of the given ApiFuture
     * @param input The future to transform
     * @param function The function to apply to the input future's result
     * @param executor The executor to run the transformation in
     * @return A future with the transformed result
     */
    static <I, O> ApiFuture<O> transformAsync(
        ApiFuture<I> input, 
        ApiAsyncFunction<I, O> function, 
        Executor executor
    );
    
    /**
     * Creates an ApiFuture whose result is a list containing the results of the given ApiFutures
     * @param futures The futures to combine
     * @return A future containing a list of all results
     */
    static <V> ApiFuture<List<V>> allAsList(
        Iterable<? extends ApiFuture<? extends V>> futures
    );
    
    /**
     * Returns a new ApiFuture whose result is taken from the given primary input or, if the primary input fails with the given exception type, from the result provided by the fallback
     * @param input The primary input future
     * @param exceptionType The exception type to catch
     * @param callback The fallback function to apply on exception
     * @param executor The executor to run the fallback in
     * @return A future with error handling applied
     */
    static <V, X extends Throwable> ApiFuture<V> catching(
        ApiFuture<? extends V> input, 
        Class<X> exceptionType, 
        ApiFunction<? super X, ? extends V> callback, 
        Executor executor
    );
    
    /**
     * Returns a new ApiFuture whose result is asynchronously taken from the given primary input or, if the primary input fails with the given exception type, from the result provided by the fallback
     * @param input The primary input future
     * @param exceptionType The exception type to catch
     * @param callback The async fallback function to apply on exception
     * @param executor The executor to run the fallback in
     * @return A future with async error handling applied
     */
    static <V, X extends Throwable> ApiFuture<V> catchingAsync(
        ApiFuture<V> input, 
        Class<X> exceptionType, 
        ApiAsyncFunction<X, V> callback, 
        Executor executor
    );
    
    /**
     * Creates an ApiFuture whose result is a list containing the results of the given ApiFutures, in the same order, but where null is returned for failed futures
     * @param futures The futures to combine
     * @return A future containing a list with successful results and nulls for failures
     */
    @BetaApi
    static <V> ApiFuture<List<V>> successfulAsList(
        Iterable<? extends ApiFuture<? extends V>> futures
    );
}

Usage Examples:

import com.google.api.core.ApiFuture;
import com.google.api.core.ApiFutures;
import com.google.common.util.concurrent.MoreExecutors;

// Create immediate futures
ApiFuture<String> completedFuture = ApiFutures.immediateFuture("Hello");
ApiFuture<String> failedFuture = ApiFutures.immediateFailedFuture(new RuntimeException("Error"));

// Transform results
ApiFuture<Integer> lengthFuture = ApiFutures.transform(
    completedFuture,
    String::length,
    MoreExecutors.directExecutor()
);

// Handle errors
ApiFuture<String> withFallback = ApiFutures.catching(
    failedFuture,
    RuntimeException.class,
    throwable -> "Default value",
    MoreExecutors.directExecutor()
);

// Combine multiple futures
List<ApiFuture<String>> futures = Arrays.asList(
    ApiFutures.immediateFuture("one"),
    ApiFutures.immediateFuture("two")
);
ApiFuture<List<String>> combined = ApiFutures.allAsList(futures);

SettableApiFuture

An ApiFuture whose result can be set programmatically. Useful for bridging callback-based APIs to the future-based programming model.

/**
 * An ApiFuture whose result can be set manually
 * @param <V> The result type
 */
class SettableApiFuture<V> implements ApiFuture<V> {
    /**
     * Creates a new SettableApiFuture that can be completed or cancelled by a later method call
     * @return A new SettableApiFuture
     */
    static <V> SettableApiFuture<V> create();
    
    /**
     * Sets the result of this Future unless this Future has already been cancelled or set
     * @param value The value to set
     * @return True if this attempt completed this Future, false if it was already complete
     */
    boolean set(V value);
    
    /**
     * Sets the result of this Future to the given exception unless this Future has already been cancelled or set
     * @param throwable The exception to set
     * @return True if this attempt completed this Future, false if it was already complete
     */
    boolean setException(Throwable throwable);
}

Usage Example:

import com.google.api.core.SettableApiFuture;

// Create a settable future
SettableApiFuture<String> future = SettableApiFuture.create();

// Set the result from another thread or callback
someAsyncOperation(result -> {
    if (result.isSuccess()) {
        future.set(result.getValue());
    } else {
        future.setException(result.getException());
    }
});

// Use the future
String result = future.get(); // Blocks until set

Functional Interfaces

Core functional interfaces for transformations and callbacks in the async programming model.

/**
 * A transformation function from one type to another
 * @param <F> The input type
 * @param <T> The output type
 */
@FunctionalInterface
interface ApiFunction<F, T> {
    /**
     * Applies this function to the given argument
     * @param input The function argument
     * @return The function result
     */
    T apply(F input);
}

/**
 * A transformation function that returns an ApiFuture
 * @param <I> The input type
 * @param <O> The output type
 */
@FunctionalInterface  
interface ApiAsyncFunction<I, O> {
    /**
     * Applies this function to the given argument, returning an ApiFuture
     * @param input The function argument
     * @return An ApiFuture containing the function result
     * @throws Exception If the transformation fails
     */
    ApiFuture<O> apply(I input) throws Exception;
}

/**
 * A callback to be notified when an ApiFuture completes
 * @param <V> The result type
 */
interface ApiFutureCallback<V> {
    /**
     * Invoked when a computation fails or is cancelled
     * @param t The failure cause
     */
    void onFailure(Throwable t);
    
    /**
     * Invoked when a computation completes successfully
     * @param result The computation result
     */
    void onSuccess(V result);
}

Service Lifecycle Management

Interfaces and base classes for managing the lifecycle of long-running services with startup, shutdown, and state monitoring.

/**
 * An object with an operational state, asynchronous startup and shutdown lifecycles
 */
interface ApiService {
    /**
     * If the service state is NEW, this initiates service startup and returns immediately
     * @return This service instance
     */
    ApiService startAsync();
    
    /**
     * If the service is STARTING or RUNNING, this initiates service shutdown and returns immediately
     * @return This service instance
     */
    ApiService stopAsync();
    
    /**
     * Waits for the Service to reach the RUNNING state
     * @throws IllegalStateException If the service reaches a state other than RUNNING
     */
    void awaitRunning();
    
    /**
     * Waits for the Service to reach the RUNNING state for no more than the given time
     * @param timeout The maximum time to wait
     * @param unit The time unit of the timeout argument
     * @throws TimeoutException If the service does not reach RUNNING within the timeout
     * @throws IllegalStateException If the service reaches a state other than RUNNING
     */
    void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException;
    
    /**
     * Waits for the Service to reach the TERMINATED state
     * @throws IllegalStateException If the service fails
     */
    void awaitTerminated();
    
    /**
     * Waits for the Service to reach the TERMINATED state for no more than the given time
     * @param timeout The maximum time to wait
     * @param unit The time unit of the timeout argument
     * @throws TimeoutException If the service does not reach TERMINATED within the timeout
     * @throws IllegalStateException If the service fails
     */
    void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException;
    
    /**
     * Returns true if this service is RUNNING
     * @return True if the service is running
     */
    boolean isRunning();
    
    /**
     * Returns the current state of this service
     * @return The current service state
     */
    State state();
    
    /**
     * Returns the Throwable that caused this service to fail
     * @return The failure cause, or null if the service has not failed
     */
    Throwable failureCause();
    
    /**
     * Registers a Listener to be executed on the given executor
     * @param listener The listener to register
     * @param executor The executor to run the listener on
     */
    void addListener(Listener listener, Executor executor);
    
    /**
     * The lifecycle states of a service
     */
    enum State {
        NEW, STARTING, RUNNING, STOPPING, TERMINATED, FAILED
    }
    
    /**
     * A listener for the various state changes that a Service goes through in its lifecycle
     */
    abstract class Listener {
        /**
         * Called when the service transitions from NEW to STARTING
         */
        public void starting() {}
        
        /**
         * Called when the service transitions from STARTING to RUNNING
         */
        public void running() {}
        
        /**
         * Called when the service transitions to the STOPPING state
         * @param from The previous state
         */
        public void stopping(State from) {}
        
        /**
         * Called when the service transitions to the TERMINATED state
         * @param from The previous state  
         */
        public void terminated(State from) {}
        
        /**
         * Called when the service transitions to the FAILED state
         * @param from The previous state
         * @param failure The failure that caused the transition
         */
        public void failed(State from, Throwable failure) {}
    }
}

AbstractApiService

Base implementation of ApiService that handles state management and listener notification. Subclasses only need to implement the actual start and stop logic.

/**
 * Base implementation of ApiService
 */
abstract class AbstractApiService implements ApiService {
    /**
     * Invoked to start the service. This method should be idempotent
     */
    protected abstract void doStart();
    
    /**
     * Invoked to stop the service. This method should be idempotent
     */
    protected abstract void doStop();
    
    /**
     * Implementing classes should invoke this method once their service has started
     */
    protected final void notifyStarted();
    
    /**
     * Implementing classes should invoke this method once their service has stopped
     */
    protected final void notifyStopped();
    
    /**
     * Invoke this method to transition the service to the FAILED state
     * @param cause The exception that caused the service to fail
     */
    protected final void notifyFailed(Throwable cause);
}

Usage Example:

import com.google.api.core.AbstractApiService;

public class MyService extends AbstractApiService {
    private volatile boolean running = false;
    
    @Override
    protected void doStart() {
        // Start your service logic here
        new Thread(() -> {
            try {
                // Initialize resources
                running = true;
                notifyStarted(); // Signal that startup completed
                
                // Run service loop
                while (running) {
                    // Service work
                    Thread.sleep(1000);
                }
            } catch (Exception e) {
                notifyFailed(e); // Signal failure
            }
        }).start();
    }
    
    @Override
    protected void doStop() {
        running = false;
        // Cleanup resources
        notifyStopped(); // Signal that shutdown completed
    }
}

// Usage
MyService service = new MyService();
service.startAsync().awaitRunning();
// Service is now running
service.stopAsync().awaitTerminated();
// Service is now stopped

Clock Abstractions

Abstraction for time sources that can be mocked in tests, providing both high-resolution nanosecond timing and standard millisecond timing.

/**
 * A supplier of time values
 */
interface ApiClock {
    /**
     * Returns the current value of the running JVM's high-resolution time source, in nanoseconds
     * @return The current value of the running JVM's high-resolution time source, in nanoseconds
     */
    long nanoTime();
    
    /**
     * Returns the current time in milliseconds
     * @return The difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC
     */
    long millisTime();
}

/**
 * A Clock that returns the current system nano time
 */
class NanoClock implements ApiClock {
    /**
     * Returns the default NanoClock instance
     * @return The default clock instance
     */
    static ApiClock getDefaultClock();
    
    @Override
    public long nanoTime() {
        return System.nanoTime();
    }
    
    @Override  
    public long millisTime() {
        return java.util.concurrent.TimeUnit.MILLISECONDS.convert(nanoTime(), java.util.concurrent.TimeUnit.NANOSECONDS);
    }
}

/**
 * A Clock that returns the current system time in milliseconds
 */
class CurrentMillisClock implements ApiClock {
    /**
     * Returns the default CurrentMillisClock instance
     * @return The default clock instance
     */
    static ApiClock getDefaultClock();
    
    @Override
    public long nanoTime() {
        return java.util.concurrent.TimeUnit.NANOSECONDS.convert(millisTime(), java.util.concurrent.TimeUnit.MILLISECONDS);
    }
    
    @Override
    public long millisTime() {
        return System.currentTimeMillis(); 
    }
}

Base Future Classes

Abstract base classes for implementing custom ApiFuture types and forwarding decorators.

/**
 * An abstract implementation of ApiFuture, for easier extension
 * @param <V> The result type returned by this Future's get method
 */
abstract class AbstractApiFuture<V> implements ApiFuture<V> {
    /**
     * Sets the result of this AbstractApiFuture unless it has already been cancelled or set
     * @param value The value to set
     * @return True if the value was set, false if the future was already complete
     */
    protected boolean set(V value);
    
    /**
     * Sets the result of this AbstractApiFuture to the given exception unless it has already been cancelled or set
     * @param throwable The exception to set
     * @return True if the exception was set, false if the future was already complete
     */
    protected boolean setException(Throwable throwable);
    
    /**
     * Subclasses can override this method to be notified when this future is cancelled
     */
    protected void interruptTask();
}

/**
 * A Future that forwards all calls to another future
 * @param <T> The result type returned by this Future's get method
 */
class ForwardingApiFuture<T> implements ApiFuture<T> {
    /**
     * Constructor that takes the delegate future
     * @param delegate The future to forward calls to
     */
    protected ForwardingApiFuture(ApiFuture<T> delegate);
}

Install with Tessl CLI

npx tessl i tessl/maven-com-google-api--api-common

docs

core-api.md

index.md

path-template.md

resource-names.md

tile.json