How do you configure CaffeineCacheManager, and how does JCacheCacheManager differ as a provider bridge?
answer
- Caffeine: one spec for all caches
- setCaffeine / setCacheSpecification string
- constructor names => fixed, no dynamic
- asyncCacheMode for CompletableFuture
- JCache = adapt javax.cache provider config
basics
~20 sConfigure CaffeineCacheManager by giving it a Caffeine builder or a spec string (e.g. maximumSize, expireAfterWrite). JCacheCacheManager instead wraps a JSR-107 javax.cache.CacheManager from a provider like Ehcache 3, so the provider's own config file drives behaviour.
solid answer
~40 sCaffeineCacheManager applies one Caffeine configuration to every cache it creates. You set it via setCaffeine(Caffeine.newBuilder().maximumSize(...).expireAfterWrite(...)), setCaffeineSpec(CaffeineSpec.parse(...)), or a plain string with setCacheSpecification("maximumSize=500,expireAfterWrite=10m"). Passing cache names to the constructor fixes the set and disables dynamic creation; otherwise caches are created on demand. It can also run in async mode for reactive/CompletableFuture returns. JCacheCacheManager is different in kind: it doesn't store anything itself — it adapts a standardized javax.cache.CacheManager (JSR-107). You bring a compliant provider (Ehcache 3, Hazelcast, Infinispan), configure per-cache policies in that provider's native config, and Spring wraps each javax.cache.Cache. Caffeine gives per-manager Java config; JCache gives vendor-neutral, provider-driven config and features like listeners and standardized statistics.
code
java · 16 lines@Bean
public CacheManager caffeine() {
CaffeineCacheManager mgr = new CaffeineCacheManager();
mgr.setCacheSpecification("maximumSize=1000,expireAfterWrite=10m,recordStats");
// per-cache override sharing the same manager:
mgr.registerCustomCache("shortLived",
Caffeine.newBuilder().expireAfterWrite(Duration.ofSeconds(30)).build());
return mgr;
}
@Bean
public CacheManager jcache() {
javax.cache.CacheManager jsr107 =
Caching.getCachingProvider().getCacheManager(); // e.g. Ehcache 3 provider
return new JCacheCacheManager(jsr107);
}go deeper
Know Caffeine is configured with a spec string and JCache wraps a JSR-107 provider.
Configure Caffeine three ways and explain the single-spec limitation and JCache adapter role.
Handle per-cache TTL strategies, async mode, and provider portability trade-offs.
Design multi-provider topologies and standardize on JSR-107 vs local Caffeine across services.
## CaffeineCacheManager configuration `CaffeineCacheManager` (in `spring-context-support`) adapts the Caffeine library. Key point: **one Caffeine specification is shared by all caches this manager builds** — you cannot give two caches different TTLs from a single CaffeineCacheManager unless you register pre-built native caches. Ways to configure: - `setCaffeine(Caffeine<Object,Object> builder)` — full programmatic control: `maximumSize`, `maximumWeight`+`weigher`, `expireAfterWrite`, `expireAfterAccess`, `refreshAfterWrite` (needs a `CacheLoader`), `weakKeys`, `softValues`, `recordStats`. - `setCaffeineSpec(CaffeineSpec)` — a parsed spec object. - `setCacheSpecification(String)` — string form, e.g. `"maximumSize=1000,expireAfterWrite=5m,recordStats"`. - Constructor names, e.g. `new CaffeineCacheManager("a","b")`, **fix** the cache set and turn off dynamic creation; the no-arg constructor leaves it dynamic. - `setAllowNullValues(boolean)` — whether a `null` return is cached (default true; stored as an internal placeholder). - `setAsyncCacheMode(true)` — backs caches with Caffeine `AsyncCache`, required for `@Cacheable` on methods returning `CompletableFuture`/reactive types. - To give different caches different policies from one manager, register native caches with `registerCustomCache(name, nativeCaffeineCache)`. Spring Boot can auto-configure this: with Caffeine on the classpath and `spring.cache.type=caffeine`, `spring.cache.caffeine.spec=...` feeds the spec. ## JCacheCacheManager (JSR-107) as a bridge JSR-107 (`javax.cache`, aka JCache) is a **standard caching API**. Providers implementing it include Ehcache 3, Hazelcast, Infinispan, and others. Spring's `JCacheCacheManager` does not implement a cache store; it **adapts an existing `javax.cache.CacheManager`**: 1. A `javax.cache.spi.CachingProvider` is discovered (`Caching.getCachingProvider()`). 2. It produces a `javax.cache.CacheManager`, typically configured from the provider's native config (e.g. an Ehcache 3 XML at a URI) or programmatically with `MutableConfiguration`. 3. Spring's `JCacheCacheManager` wraps it, exposing each `javax.cache.Cache` as a Spring `Cache`. Because config lives in the JCache provider, **per-cache TTL, expiry policies, listeners, and statistics are defined the JSR-107 way**, not through Spring. This gives vendor portability: swap Ehcache for Hazelcast by changing the provider, not your Spring code. > Note: this JCacheCacheManager is Spring's cache-abstraction adapter (`org.springframework.cache.jcache.JCacheCacheManager`). It is distinct from JSR-107's own `@CacheResult` annotations, which Spring can also honour separately. ## When to choose which - **Caffeine**: single JVM, want the fastest local cache, config in Java/properties, no distribution. Default modern local choice. - **JCache**: you need a standardized/portable provider, richer per-cache policies, JMX statistics, or a provider that also offers clustering (Hazelcast/Infinispan). ## Gotchas - Sharing one Caffeine spec across all caches surprises people who expect per-name TTL; use `registerCustomCache` or multiple managers (routed by `CompositeCacheManager`/`cacheResolver`). - `refreshAfterWrite` needs a `CacheLoader`; without one it behaves like no refresh. - Async mode is mandatory for `CompletableFuture`-returning cached methods; forgetting it causes type errors. - With JCache, forgetting to pre-define a cache in the provider can throw when Spring requests an unknown name (depends on provider's dynamic-cache support).
- How do you give two caches different TTLs when both are managed by Caffeine?One CaffeineCacheManager shares a single spec, so either register per-name native caches via registerCustomCache, or run multiple CaffeineCacheManagers routed by a CompositeCacheManager or a CacheResolver.
- Does JCacheCacheManager store cache entries itself?No. It's an adapter over a JSR-107 javax.cache.CacheManager; the actual store, TTLs, and policies come from the underlying provider (Ehcache 3, Hazelcast, etc.).
saying these in an interview costs you the question
- Believing CaffeineCacheManager supports independent per-cache specs from a single manager without extra work
- Thinking JCacheCacheManager is its own cache store rather than an adapter
- Forgetting asyncCacheMode is required for CompletableFuture-returning cached methods