Skip to content
Bluetape4k docs1.11

JCache provider, manager, and configuration

Latest stable Based on Bluetape4k release 1.11.0

LettuceCachingProvider is registered in META-INF/services/javax.cache.spi.CachingProvider. JCache can discover it, and the provider reuses one LettuceCacheManager for each (ClassLoader, URI) pair.

val provider = Caching.getCachingProvider(
"io.bluetape4k.cache.jcache.LettuceCachingProvider"
)
val manager = provider.getCacheManager(
URI("redis://redis.example:6379/2"),
Thread.currentThread().contextClassLoader,
)

Without a URI, the provider uses its logical lettuce-jcache-default URI and connects to redis://localhost:6379. The ClassLoader is part of manager identity, which matters in plugin and application-server environments.

A provider-created manager also creates and shuts down its RedisClient. LettuceJCaching.cacheManagerOf(redisClient) instead reuses an application-owned client and does not close it.

val redisClient = RedisClient.create("redis://localhost:6379")
val cache = LettuceJCaching.getOrCreate<String, User>(
redisClient, "users-v1", ttlSeconds = 600,
)
try {
cache.put("42", user)
} finally {
cache.close()
redisClient.shutdown()
}

LettuceJCaching keeps one manager per client. Align manager and client lifetime at the application boundary instead of repeatedly closing and reopening the cached manager.

One JCache maps to one Redis hash. A JCache key becomes a string hash field, and the value becomes bytes produced by the selected LettuceBinaryCodec.

Redis hash: users-v1
field "42" -> <lz4+fory bytes>
field "84" -> <lz4+fory bytes>

The default key encoder calls toString(). Iteration over non-String keys also needs a decoder.

val config = lettuceCacheConfigOf<Int, User>(
ttlSeconds = 600,
keyCodec = Int::toString,
keyDecoder = String::toInt,
)

Direct lookup can work without the decoder, but iteration cannot reconstruct the key and throws CacheException.

LettuceCacheConfig.ttlSeconds is not per-entry expiry. A successful write refreshes the TTL of the Redis hash, so all entries under the cache name expire together.

  • Redis 8+ uses the detected HSETEX path.
  • Older servers fall back to HSET or HMSET followed by EXPIRE.
  • null means no expiry.
  • Continued writes extend the whole hash lifetime.

Use separate cache names or the native near cache when entries need independent TTLs.

createCache rejects blank and duplicate names. Typed getCache rejects key or value types that differ from the stored configuration. Operations after manager close fail with IllegalStateException.

destroyCache clears the Redis hash and closes the cache connection. cache.close() only removes the wrapper and closes its connection; Redis data remains. Do not couple process shutdown to data deletion.