or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/maven-com-github-ben-manes-caffeine--guava

Guava compatibility adapter for Caffeine caching library, enabling seamless migration from Guava caches to Caffeine's high-performance caching through familiar Guava Cache API interfaces.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
mavenpkg:maven/com.github.ben-manes.caffeine/guava@3.2.x

To install, run

npx @tessl/cli install tessl/maven-com-github-ben-manes-caffeine--guava@3.2.0

index.mddocs/

Caffeine Guava

Caffeine Guava provides a compatibility adapter that enables seamless migration from Guava caches to Caffeine's high-performance caching library. The adapter wraps Caffeine cache instances in familiar Guava Cache API interfaces, allowing applications to benefit from Caffeine's superior performance characteristics (TinyLFU admission policy, advanced eviction strategies, and optimized concurrent access) while maintaining full API compatibility with existing Guava cache code.

Package Information

  • Package Name: guava
  • Package Type: maven
  • Language: Java
  • Installation: implementation 'com.github.ben-manes.caffeine:guava:3.2.0'
  • Maven Coordinate: com.github.ben-manes.caffeine:guava

Core Imports

import com.github.benmanes.caffeine.guava.CaffeinatedGuava;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.common.cache.Cache;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.CacheLoader;

// For static factory methods
import java.util.function.Function;
import java.util.concurrent.Executor;

Basic Usage

import com.github.benmanes.caffeine.guava.CaffeinatedGuava;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.common.cache.Cache;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.CacheLoader;
import java.time.Duration;

// Create a simple Guava-compatible cache from Caffeine
Cache<String, String> cache = CaffeinatedGuava.build(
    Caffeine.newBuilder()
        .maximumSize(1000)
        .expireAfterWrite(Duration.ofMinutes(10))
);

cache.put("key", "value");
String value = cache.getIfPresent("key");

// Create a loading cache with Guava CacheLoader
LoadingCache<String, String> loadingCache = CaffeinatedGuava.build(
    Caffeine.newBuilder()
        .maximumSize(1000)
        .expireAfterAccess(Duration.ofMinutes(5)),
    new CacheLoader<String, String>() {
        @Override
        public String load(String key) throws Exception {
            return loadFromDatabase(key);
        }
    }
);

String loadedValue = loadingCache.get("key");

Architecture

The Caffeine Guava adapter is built around several key components:

  • CaffeinatedGuava: Main utility class providing static factory methods for creating Guava-compatible cache instances
  • CaffeinatedGuavaCache: Adapter that implements Guava's Cache interface while delegating to a Caffeine cache instance
  • CaffeinatedGuavaLoadingCache: Specialized adapter extending CaffeinatedGuavaCache that implements Guava's LoadingCache interface
  • Cache Loader Adapters: Internal classes that bridge between Guava and Caffeine loader interfaces, handling both single-key and bulk loading scenarios
  • Exception Translation: Automatic conversion between Caffeine and Guava exception types to maintain API compatibility

Capabilities

Cache Creation

Creates Guava Cache facades around Caffeine cache instances.

/**
 * Returns a Caffeine cache wrapped in a Guava Cache facade.
 * @param builder the configured cache builder
 * @param <K> the most general key type to create caches for
 * @param <V> the most general value type to create caches for
 * @param <K1> the key type of the cache
 * @param <V1> the value type of the cache
 * @return a cache exposed under the Guava APIs
 */
public static <K, V, K1 extends K, V1 extends V> Cache<K1, V1> build(Caffeine<K, V> builder);

Usage Example:

import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.guava.CaffeinatedGuava;
import com.google.common.cache.Cache;
import java.time.Duration;

Cache<String, Integer> cache = CaffeinatedGuava.build(
    Caffeine.newBuilder()
        .maximumSize(10000)
        .expireAfterWrite(Duration.ofHours(1))
        .recordStats()
);

// Use as a normal Guava Cache
cache.put("count", 42);
Integer count = cache.getIfPresent("count");
cache.invalidate("count");

Loading Cache Creation with Guava Loader

Creates Guava LoadingCache facades around Caffeine cache instances using Guava CacheLoader.

/**
 * Returns a Caffeine cache wrapped in a Guava LoadingCache facade.
 * @param builder the configured cache builder
 * @param loader the cache loader used to obtain new values
 * @param <K> the most general key type to create caches for
 * @param <V> the most general value type to create caches for
 * @param <K1> the key type of the cache
 * @param <V1> the value type of the cache
 * @return a cache exposed under the Guava APIs
 */
public static <K, V, K1 extends K, V1 extends V> LoadingCache<K1, V1> build(
    Caffeine<K, V> builder, 
    CacheLoader<? super K1, V1> loader
);

Usage Example:

import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.util.concurrent.ExecutionException;
import java.util.Map;
import java.util.Arrays;

LoadingCache<String, String> userCache = CaffeinatedGuava.build(
    Caffeine.newBuilder()
        .maximumSize(1000)
        .expireAfterAccess(Duration.ofMinutes(30)),
    new CacheLoader<String, String>() {
        @Override
        public String load(String userId) throws Exception {
            return fetchUserFromDatabase(userId);
        }
        
        @Override
        public Map<String, String> loadAll(Iterable<? extends String> keys) throws Exception {
            return fetchUsersFromDatabase(keys);
        }
    }
);

try {
    String user = userCache.get("user123");
    Map<String, String> users = userCache.getAll(Arrays.asList("user1", "user2"));
} catch (ExecutionException e) {
    // Handle loading exceptions
}

Loading Cache Creation with Caffeine Loader

Creates Guava LoadingCache facades around Caffeine cache instances using Caffeine CacheLoader.

/**
 * Returns a Caffeine cache wrapped in a Guava LoadingCache facade.
 * @param builder the configured cache builder
 * @param loader the cache loader used to obtain new values
 * @param <K> the most general key type to create caches for
 * @param <V> the most general value type to create caches for
 * @param <K1> the key type of the cache
 * @param <V1> the value type of the cache  
 * @return a cache exposed under the Guava APIs
 */
public static <K, V, K1 extends K, V1 extends V> LoadingCache<K1, V1> build(
    Caffeine<K, V> builder,
    com.github.benmanes.caffeine.cache.CacheLoader<? super K1, V1> loader
);

Usage Example:

import com.github.benmanes.caffeine.cache.CacheLoader;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;

LoadingCache<String, String> configCache = CaffeinatedGuava.build(
    Caffeine.newBuilder()
        .refreshAfterWrite(Duration.ofMinutes(5))
        .maximumSize(500),
    new com.github.benmanes.caffeine.cache.CacheLoader<String, String>() {
        @Override
        public String load(String key) throws Exception {
            return loadConfigValue(key);
        }
        
        @Override
        public CompletableFuture<String> asyncReload(String key, String oldValue, Executor executor) {
            return CompletableFuture.supplyAsync(() -> {
                try {
                    return loadConfigValue(key);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }, executor);
        }
    }
);

Cache Loader Adaptation

Converts Guava CacheLoader to Caffeine CacheLoader for direct use with Caffeine APIs.

/**
 * Returns a Caffeine cache loader that delegates to a Guava cache loader.
 * @param loader the cache loader used to obtain new values
 * @param <K> the type of keys
 * @param <V> the type of values
 * @return a cache loader exposed under the Caffeine APIs
 */
public static <K, V> com.github.benmanes.caffeine.cache.CacheLoader<K, V> caffeinate(
    CacheLoader<K, V> loader
);

Usage Example:

// Existing Guava CacheLoader
CacheLoader<String, String> guavaLoader = new CacheLoader<String, String>() {
    @Override
    public String load(String key) throws Exception {
        return expensiveOperation(key);
    }
};

// Convert to Caffeine CacheLoader
com.github.benmanes.caffeine.cache.CacheLoader<String, String> caffeineLoader = 
    CaffeinatedGuava.caffeinate(guavaLoader);

// Use with native Caffeine cache
com.github.benmanes.caffeine.cache.LoadingCache<String, String> nativeCache = 
    Caffeine.newBuilder()
        .maximumSize(1000)
        .build(caffeineLoader);

CacheLoader Factory Methods

Creates CacheLoader instances using static factory methods for common patterns.

from() Method

Creates a CacheLoader from a Function for simple loading scenarios.

/**
 * Returns a cache loader that uses the provided function for loading values.
 * @param function the function to use for loading values
 * @param <K> the type of keys
 * @param <V> the type of values  
 * @return a cache loader that delegates to the function
 */
public static <K, V> CacheLoader<K, V> from(Function<K, V> function);

Usage Example:

import com.google.common.cache.CacheLoader;
import java.util.function.Function;

// Create a simple loader using a lambda
CacheLoader<String, String> loader = CacheLoader.from(key -> "value-for-" + key);

// Use with cache creation
LoadingCache<String, String> cache = CaffeinatedGuava.build(
    Caffeine.newBuilder().maximumSize(1000),
    loader
);

String value = cache.get("mykey"); // Returns "value-for-mykey"

asyncReloading() Method

Wraps an existing CacheLoader to perform asynchronous reloads in the background.

/**
 * Returns a cache loader that performs asynchronous reloads.
 * @param loader the cache loader to wrap
 * @param executor the executor to use for async operations
 * @param <K> the type of keys
 * @param <V> the type of values
 * @return a cache loader that performs async reloads
 */
public static <K, V> CacheLoader<K, V> asyncReloading(
    CacheLoader<K, V> loader, 
    Executor executor
);

Usage Example:

import com.google.common.cache.CacheLoader;
import java.util.concurrent.Executors;
import java.util.concurrent.Executor;

// Original synchronous loader
CacheLoader<String, String> syncLoader = new CacheLoader<String, String>() {
    @Override
    public String load(String key) throws Exception {
        return fetchFromDatabase(key); // Slow operation
    }
};

// Wrap for asynchronous reloading
Executor executor = Executors.newFixedThreadPool(5);
CacheLoader<String, String> asyncLoader = CacheLoader.asyncReloading(syncLoader, executor);

// Use with refresh-enabled cache
LoadingCache<String, String> cache = CaffeinatedGuava.build(
    Caffeine.newBuilder()
        .maximumSize(1000)
        .refreshAfterWrite(Duration.ofMinutes(5)), // Triggers async reload
    asyncLoader
);

Types

Cache Interface

The adapter implements the complete Guava Cache interface:

public interface Cache<K, V> {
    V getIfPresent(Object key);
    V get(K key, Callable<? extends V> valueLoader) throws ExecutionException;
    ImmutableMap<K, V> getAllPresent(Iterable<?> keys);
    void put(K key, V value);
    void putAll(Map<? extends K, ? extends V> m);
    void invalidate(Object key);
    void invalidateAll(Iterable<?> keys);
    void invalidateAll();
    long size();
    CacheStats stats();
    ConcurrentMap<K, V> asMap();
    void cleanUp();
}

LoadingCache Interface

The adapter implements the complete Guava LoadingCache interface:

public interface LoadingCache<K, V> extends Cache<K, V>, Function<K, V> {
    V get(K key) throws ExecutionException;
    V getUnchecked(K key);
    ImmutableMap<K, V> getAll(Iterable<? extends K> keys) throws ExecutionException;
    V apply(K key); // Deprecated
    void refresh(K key);
}

CacheLoader Class

Standard Guava CacheLoader that can be used with the adapter:

public abstract class CacheLoader<K, V> {
    public abstract V load(K key) throws Exception;
    public Map<K, V> loadAll(Iterable<? extends K> keys) throws Exception;
    public ListenableFuture<V> reload(K key, V oldValue) throws Exception;
    
    // Static factory methods
    public static <K, V> CacheLoader<K, V> from(Function<K, V> function);
    public static <K, V> CacheLoader<K, V> asyncReloading(
        CacheLoader<K, V> loader, Executor executor);
}

Exception Types

The adapter handles and translates various exception types:

// Thrown when a cache loader returns null
public class InvalidCacheLoadException extends RuntimeException;

// Wrapper for checked exceptions during cache loading  
public class ExecutionException extends Exception;

// Wrapper for runtime exceptions during cache loading
public class UncheckedExecutionException extends RuntimeException;

// Wrapper for errors during cache loading
public class ExecutionError extends Error;

Error Handling

The Caffeine Guava adapter provides comprehensive exception translation between Caffeine and Guava APIs:

  • Null Values: InvalidCacheLoadException is thrown when cache loaders return null values
  • Checked Exceptions: Wrapped in ExecutionException for methods that declare it
  • Runtime Exceptions: Wrapped in UncheckedExecutionException for unchecked methods
  • Errors: Wrapped in ExecutionError to maintain proper error propagation
  • Interrupted Operations: Properly handle thread interruption during cache loading

Example Error Handling:

import java.util.concurrent.ExecutionException;
import com.google.common.cache.CacheLoader.InvalidCacheLoadException;

try {
    String value = loadingCache.get("key");
} catch (ExecutionException e) {
    Throwable cause = e.getCause();
    if (cause instanceof MyCustomException) {
        // Handle specific exception
    }
} catch (InvalidCacheLoadException e) {
    // Handle null value from loader
}