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.
npx @tessl/cli install tessl/maven-com-github-ben-manes-caffeine--guava@3.2.00
# Caffeine Guava
1
2
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.
3
4
## Package Information
5
6
- **Package Name**: guava
7
- **Package Type**: maven
8
- **Language**: Java
9
- **Installation**: `implementation 'com.github.ben-manes.caffeine:guava:3.2.0'`
10
- **Maven Coordinate**: `com.github.ben-manes.caffeine:guava`
11
12
## Core Imports
13
14
```java
15
import com.github.benmanes.caffeine.guava.CaffeinatedGuava;
16
import com.github.benmanes.caffeine.cache.Caffeine;
17
import com.google.common.cache.Cache;
18
import com.google.common.cache.LoadingCache;
19
import com.google.common.cache.CacheLoader;
20
21
// For static factory methods
22
import java.util.function.Function;
23
import java.util.concurrent.Executor;
24
```
25
26
## Basic Usage
27
28
```java
29
import com.github.benmanes.caffeine.guava.CaffeinatedGuava;
30
import com.github.benmanes.caffeine.cache.Caffeine;
31
import com.google.common.cache.Cache;
32
import com.google.common.cache.LoadingCache;
33
import com.google.common.cache.CacheLoader;
34
import java.time.Duration;
35
36
// Create a simple Guava-compatible cache from Caffeine
37
Cache<String, String> cache = CaffeinatedGuava.build(
38
Caffeine.newBuilder()
39
.maximumSize(1000)
40
.expireAfterWrite(Duration.ofMinutes(10))
41
);
42
43
cache.put("key", "value");
44
String value = cache.getIfPresent("key");
45
46
// Create a loading cache with Guava CacheLoader
47
LoadingCache<String, String> loadingCache = CaffeinatedGuava.build(
48
Caffeine.newBuilder()
49
.maximumSize(1000)
50
.expireAfterAccess(Duration.ofMinutes(5)),
51
new CacheLoader<String, String>() {
52
@Override
53
public String load(String key) throws Exception {
54
return loadFromDatabase(key);
55
}
56
}
57
);
58
59
String loadedValue = loadingCache.get("key");
60
```
61
62
## Architecture
63
64
The Caffeine Guava adapter is built around several key components:
65
66
- **CaffeinatedGuava**: Main utility class providing static factory methods for creating Guava-compatible cache instances
67
- **CaffeinatedGuavaCache**: Adapter that implements Guava's `Cache` interface while delegating to a Caffeine cache instance
68
- **CaffeinatedGuavaLoadingCache**: Specialized adapter extending `CaffeinatedGuavaCache` that implements Guava's `LoadingCache` interface
69
- **Cache Loader Adapters**: Internal classes that bridge between Guava and Caffeine loader interfaces, handling both single-key and bulk loading scenarios
70
- **Exception Translation**: Automatic conversion between Caffeine and Guava exception types to maintain API compatibility
71
72
## Capabilities
73
74
### Cache Creation
75
76
Creates Guava Cache facades around Caffeine cache instances.
77
78
```java { .api }
79
/**
80
* Returns a Caffeine cache wrapped in a Guava Cache facade.
81
* @param builder the configured cache builder
82
* @param <K> the most general key type to create caches for
83
* @param <V> the most general value type to create caches for
84
* @param <K1> the key type of the cache
85
* @param <V1> the value type of the cache
86
* @return a cache exposed under the Guava APIs
87
*/
88
public static <K, V, K1 extends K, V1 extends V> Cache<K1, V1> build(Caffeine<K, V> builder);
89
```
90
91
**Usage Example:**
92
93
```java
94
import com.github.benmanes.caffeine.cache.Caffeine;
95
import com.github.benmanes.caffeine.guava.CaffeinatedGuava;
96
import com.google.common.cache.Cache;
97
import java.time.Duration;
98
99
Cache<String, Integer> cache = CaffeinatedGuava.build(
100
Caffeine.newBuilder()
101
.maximumSize(10000)
102
.expireAfterWrite(Duration.ofHours(1))
103
.recordStats()
104
);
105
106
// Use as a normal Guava Cache
107
cache.put("count", 42);
108
Integer count = cache.getIfPresent("count");
109
cache.invalidate("count");
110
```
111
112
### Loading Cache Creation with Guava Loader
113
114
Creates Guava LoadingCache facades around Caffeine cache instances using Guava CacheLoader.
115
116
```java { .api }
117
/**
118
* Returns a Caffeine cache wrapped in a Guava LoadingCache facade.
119
* @param builder the configured cache builder
120
* @param loader the cache loader used to obtain new values
121
* @param <K> the most general key type to create caches for
122
* @param <V> the most general value type to create caches for
123
* @param <K1> the key type of the cache
124
* @param <V1> the value type of the cache
125
* @return a cache exposed under the Guava APIs
126
*/
127
public static <K, V, K1 extends K, V1 extends V> LoadingCache<K1, V1> build(
128
Caffeine<K, V> builder,
129
CacheLoader<? super K1, V1> loader
130
);
131
```
132
133
**Usage Example:**
134
135
```java
136
import com.google.common.cache.CacheLoader;
137
import com.google.common.cache.LoadingCache;
138
import java.util.concurrent.ExecutionException;
139
import java.util.Map;
140
import java.util.Arrays;
141
142
LoadingCache<String, String> userCache = CaffeinatedGuava.build(
143
Caffeine.newBuilder()
144
.maximumSize(1000)
145
.expireAfterAccess(Duration.ofMinutes(30)),
146
new CacheLoader<String, String>() {
147
@Override
148
public String load(String userId) throws Exception {
149
return fetchUserFromDatabase(userId);
150
}
151
152
@Override
153
public Map<String, String> loadAll(Iterable<? extends String> keys) throws Exception {
154
return fetchUsersFromDatabase(keys);
155
}
156
}
157
);
158
159
try {
160
String user = userCache.get("user123");
161
Map<String, String> users = userCache.getAll(Arrays.asList("user1", "user2"));
162
} catch (ExecutionException e) {
163
// Handle loading exceptions
164
}
165
```
166
167
### Loading Cache Creation with Caffeine Loader
168
169
Creates Guava LoadingCache facades around Caffeine cache instances using Caffeine CacheLoader.
170
171
```java { .api }
172
/**
173
* Returns a Caffeine cache wrapped in a Guava LoadingCache facade.
174
* @param builder the configured cache builder
175
* @param loader the cache loader used to obtain new values
176
* @param <K> the most general key type to create caches for
177
* @param <V> the most general value type to create caches for
178
* @param <K1> the key type of the cache
179
* @param <V1> the value type of the cache
180
* @return a cache exposed under the Guava APIs
181
*/
182
public static <K, V, K1 extends K, V1 extends V> LoadingCache<K1, V1> build(
183
Caffeine<K, V> builder,
184
com.github.benmanes.caffeine.cache.CacheLoader<? super K1, V1> loader
185
);
186
```
187
188
**Usage Example:**
189
190
```java
191
import com.github.benmanes.caffeine.cache.CacheLoader;
192
import java.util.concurrent.CompletableFuture;
193
import java.util.concurrent.Executor;
194
195
LoadingCache<String, String> configCache = CaffeinatedGuava.build(
196
Caffeine.newBuilder()
197
.refreshAfterWrite(Duration.ofMinutes(5))
198
.maximumSize(500),
199
new com.github.benmanes.caffeine.cache.CacheLoader<String, String>() {
200
@Override
201
public String load(String key) throws Exception {
202
return loadConfigValue(key);
203
}
204
205
@Override
206
public CompletableFuture<String> asyncReload(String key, String oldValue, Executor executor) {
207
return CompletableFuture.supplyAsync(() -> {
208
try {
209
return loadConfigValue(key);
210
} catch (Exception e) {
211
throw new RuntimeException(e);
212
}
213
}, executor);
214
}
215
}
216
);
217
```
218
219
### Cache Loader Adaptation
220
221
Converts Guava CacheLoader to Caffeine CacheLoader for direct use with Caffeine APIs.
222
223
```java { .api }
224
/**
225
* Returns a Caffeine cache loader that delegates to a Guava cache loader.
226
* @param loader the cache loader used to obtain new values
227
* @param <K> the type of keys
228
* @param <V> the type of values
229
* @return a cache loader exposed under the Caffeine APIs
230
*/
231
public static <K, V> com.github.benmanes.caffeine.cache.CacheLoader<K, V> caffeinate(
232
CacheLoader<K, V> loader
233
);
234
```
235
236
**Usage Example:**
237
238
```java
239
// Existing Guava CacheLoader
240
CacheLoader<String, String> guavaLoader = new CacheLoader<String, String>() {
241
@Override
242
public String load(String key) throws Exception {
243
return expensiveOperation(key);
244
}
245
};
246
247
// Convert to Caffeine CacheLoader
248
com.github.benmanes.caffeine.cache.CacheLoader<String, String> caffeineLoader =
249
CaffeinatedGuava.caffeinate(guavaLoader);
250
251
// Use with native Caffeine cache
252
com.github.benmanes.caffeine.cache.LoadingCache<String, String> nativeCache =
253
Caffeine.newBuilder()
254
.maximumSize(1000)
255
.build(caffeineLoader);
256
```
257
258
### CacheLoader Factory Methods
259
260
Creates CacheLoader instances using static factory methods for common patterns.
261
262
#### from() Method
263
264
Creates a CacheLoader from a Function for simple loading scenarios.
265
266
```java { .api }
267
/**
268
* Returns a cache loader that uses the provided function for loading values.
269
* @param function the function to use for loading values
270
* @param <K> the type of keys
271
* @param <V> the type of values
272
* @return a cache loader that delegates to the function
273
*/
274
public static <K, V> CacheLoader<K, V> from(Function<K, V> function);
275
```
276
277
**Usage Example:**
278
279
```java
280
import com.google.common.cache.CacheLoader;
281
import java.util.function.Function;
282
283
// Create a simple loader using a lambda
284
CacheLoader<String, String> loader = CacheLoader.from(key -> "value-for-" + key);
285
286
// Use with cache creation
287
LoadingCache<String, String> cache = CaffeinatedGuava.build(
288
Caffeine.newBuilder().maximumSize(1000),
289
loader
290
);
291
292
String value = cache.get("mykey"); // Returns "value-for-mykey"
293
```
294
295
#### asyncReloading() Method
296
297
Wraps an existing CacheLoader to perform asynchronous reloads in the background.
298
299
```java { .api }
300
/**
301
* Returns a cache loader that performs asynchronous reloads.
302
* @param loader the cache loader to wrap
303
* @param executor the executor to use for async operations
304
* @param <K> the type of keys
305
* @param <V> the type of values
306
* @return a cache loader that performs async reloads
307
*/
308
public static <K, V> CacheLoader<K, V> asyncReloading(
309
CacheLoader<K, V> loader,
310
Executor executor
311
);
312
```
313
314
**Usage Example:**
315
316
```java
317
import com.google.common.cache.CacheLoader;
318
import java.util.concurrent.Executors;
319
import java.util.concurrent.Executor;
320
321
// Original synchronous loader
322
CacheLoader<String, String> syncLoader = new CacheLoader<String, String>() {
323
@Override
324
public String load(String key) throws Exception {
325
return fetchFromDatabase(key); // Slow operation
326
}
327
};
328
329
// Wrap for asynchronous reloading
330
Executor executor = Executors.newFixedThreadPool(5);
331
CacheLoader<String, String> asyncLoader = CacheLoader.asyncReloading(syncLoader, executor);
332
333
// Use with refresh-enabled cache
334
LoadingCache<String, String> cache = CaffeinatedGuava.build(
335
Caffeine.newBuilder()
336
.maximumSize(1000)
337
.refreshAfterWrite(Duration.ofMinutes(5)), // Triggers async reload
338
asyncLoader
339
);
340
```
341
342
## Types
343
344
### Cache Interface
345
346
The adapter implements the complete Guava Cache interface:
347
348
```java { .api }
349
public interface Cache<K, V> {
350
V getIfPresent(Object key);
351
V get(K key, Callable<? extends V> valueLoader) throws ExecutionException;
352
ImmutableMap<K, V> getAllPresent(Iterable<?> keys);
353
void put(K key, V value);
354
void putAll(Map<? extends K, ? extends V> m);
355
void invalidate(Object key);
356
void invalidateAll(Iterable<?> keys);
357
void invalidateAll();
358
long size();
359
CacheStats stats();
360
ConcurrentMap<K, V> asMap();
361
void cleanUp();
362
}
363
```
364
365
### LoadingCache Interface
366
367
The adapter implements the complete Guava LoadingCache interface:
368
369
```java { .api }
370
public interface LoadingCache<K, V> extends Cache<K, V>, Function<K, V> {
371
V get(K key) throws ExecutionException;
372
V getUnchecked(K key);
373
ImmutableMap<K, V> getAll(Iterable<? extends K> keys) throws ExecutionException;
374
V apply(K key); // Deprecated
375
void refresh(K key);
376
}
377
```
378
379
### CacheLoader Class
380
381
Standard Guava CacheLoader that can be used with the adapter:
382
383
```java { .api }
384
public abstract class CacheLoader<K, V> {
385
public abstract V load(K key) throws Exception;
386
public Map<K, V> loadAll(Iterable<? extends K> keys) throws Exception;
387
public ListenableFuture<V> reload(K key, V oldValue) throws Exception;
388
389
// Static factory methods
390
public static <K, V> CacheLoader<K, V> from(Function<K, V> function);
391
public static <K, V> CacheLoader<K, V> asyncReloading(
392
CacheLoader<K, V> loader, Executor executor);
393
}
394
```
395
396
### Exception Types
397
398
The adapter handles and translates various exception types:
399
400
```java { .api }
401
// Thrown when a cache loader returns null
402
public class InvalidCacheLoadException extends RuntimeException;
403
404
// Wrapper for checked exceptions during cache loading
405
public class ExecutionException extends Exception;
406
407
// Wrapper for runtime exceptions during cache loading
408
public class UncheckedExecutionException extends RuntimeException;
409
410
// Wrapper for errors during cache loading
411
public class ExecutionError extends Error;
412
```
413
414
## Error Handling
415
416
The Caffeine Guava adapter provides comprehensive exception translation between Caffeine and Guava APIs:
417
418
- **Null Values**: `InvalidCacheLoadException` is thrown when cache loaders return null values
419
- **Checked Exceptions**: Wrapped in `ExecutionException` for methods that declare it
420
- **Runtime Exceptions**: Wrapped in `UncheckedExecutionException` for unchecked methods
421
- **Errors**: Wrapped in `ExecutionError` to maintain proper error propagation
422
- **Interrupted Operations**: Properly handle thread interruption during cache loading
423
424
**Example Error Handling:**
425
426
```java
427
import java.util.concurrent.ExecutionException;
428
import com.google.common.cache.CacheLoader.InvalidCacheLoadException;
429
430
try {
431
String value = loadingCache.get("key");
432
} catch (ExecutionException e) {
433
Throwable cause = e.getCause();
434
if (cause instanceof MyCustomException) {
435
// Handle specific exception
436
}
437
} catch (InvalidCacheLoadException e) {
438
// Handle null value from loader
439
}
440
```