You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Ramu (Jira)" <ji...@apache.org> on 2026/10/12 09:13:00 UTC

[jira] [Work started] (CAMEL-24757) camel-spring-boot: Spring Cache-backed KeyValueRepository adapter for the State Store component

     [ https://issues.apache.org/jira/browse/CAMEL-24757?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Work on CAMEL-24757 started by Ramu.
------------------------------------
> camel-spring-boot: Spring Cache-backed KeyValueRepository adapter for the State Store component
> -----------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-24757
>                 URL: https://issues.apache.org/jira/browse/CAMEL-24757
>             Project: Camel
>          Issue Type: New Feature
>          Components: camel-spring-boot
>            Reporter: Federico Mariani
>            Assignee: Ramu
>            Priority: Major
>
> h2. Background
> The State Store component (camel-state-store, since 4.23) provides a unified key-value API (put/get/putIfAbsent/delete/contains/keys/size/clear) backed by the pluggable {{KeyValueRepository}} SPI from camel-api. When no backend bean is configured, it falls back to the in-memory {{MemoryKeyValueRepository}}; for anything persistent/distributed, camel-api already ships implementations for Caffeine, Cassandra, Ehcache, Hazelcast, Infinispan, JCache, JDBC, JPA, Kafka and Redis.
> h2. Problem
> Those implementations don't line up with what Spring Boot users already have auto-configured:
> * {{RedisKeyValueRepository}} (camel-redis) is built on *Redisson* ({{RedissonClient}}), not Spring Data Redis (Lettuce/{{RedisTemplate}}), which is what {{spring-boot-starter-data-redis}} actually auto-configures. A Spring Boot user has to add Redisson separately and hand-wire a {{RedissonClient}} bean just to get a {{KeyValueRepository}}.
> * The same friction applies to Caffeine/Ehcache/Hazelcast: Camel's implementations expect Camel-flavored construction, not the {{CacheManager}} bean that {{spring-boot-starter-cache}} already auto-configures from {{spring.cache.type}}.
> So in a Spring Boot application, using the State Store component with a real backend currently means adding a second, Camel-specific client/dependency and manually wiring a bean, even when Spring Boot already manages an equivalent cache/client for you.
> h2. Proposal
> Add a {{KeyValueRepository}} implementation in *camel-spring-boot* (core auto-configuration module, not the generated starter) backed by Spring's cache abstraction ({{org.springframework.cache.Cache}} / {{CacheManager}}). Auto-configure it with {{@ConditionalOnBean(CacheManager.class)}} and {{@ConditionalOnMissingBean(KeyValueRepository.class)}}, so it only kicks in when the application already has a Spring-managed {{CacheManager}} and no explicit Camel {{KeyValueRepository}} bean.
> One adapter then covers every backend Spring Boot's cache abstraction already supports (Caffeine, Redis via Lettuce, Ehcache, Hazelcast, JCache, Couchbase, etc.) via the standard {{spring.cache.*}} properties, with no extra Camel-specific dependency or bean.
> The State Store endpoint's {{storeName}} would map 1:1 to the Spring {{Cache}} name looked up via {{CacheManager.getCache(storeName)}}.
> h2. Example usage
> Caffeine, using only spring-boot-starter-cache (no camel-caffeine dependency needed):
> {code:yaml}
> spring:
>   cache:
>     type: caffeine
>     cache-names: myStore
>     caffeine:
>       spec: maximumSize=10000,expireAfterWrite=600s
> {code}
> {code:java}
> from("direct:store")
>     .setHeader("CamelStateStoreKey", constant("myKey"))
>     .to("state-store:myStore?operation=put");
> from("direct:retrieve")
>     .setHeader("CamelStateStoreKey", constant("myKey"))
>     .to("state-store:myStore?operation=get");
> {code}
> Redis via Spring Data Redis/Lettuce (no camel-redis/Redisson dependency needed):
> {code}
> spring:
>   cache:
>     type: redis
>     cache-names: myStore
>   data:
>     redis:
>       host: localhost
>       port: 6379
> {code}
> Same route code as above - only the Spring Boot configuration changes to switch backend.
> h2. Limitations
> * *No {{keys()}} support* - Spring's {{Cache}} SPI has no portable key enumeration across backends, so the adapter would throw {{UnsupportedOperationException}} for the {{keys}} operation.
> * *No {{size()}} support* - same reason as above; {{size}} would also throw {{UnsupportedOperationException}}.
> * *No per-entry TTL* - Spring's {{Cache.put}} has no TTL parameter; TTL is fixed per cache/CacheManager configuration (e.g. the Caffeine spec or Redis entry-ttl config), not per message. The State Store {{ttl}} endpoint option and {{CamelStateStoreTtl}} header would have no effect against this backend; the adapter should log a WARN if a TTL is supplied so the mismatch isn't silent.
> * *Spring Boot only* - this lives in camel-spring-boot, not camel-api/core, so it is not available to other runtimes (Quarkus, camel-main, etc.); those keep using the existing backend-specific KeyValueRepository implementations.
> * *Cache pre-declaration* - some {{CacheManager}} implementations require cache names to be pre-declared (e.g. via {{spring.cache.cache-names}}); a {{storeName}} without a matching configured cache would fail to resolve, unlike the always-available in-memory default.
> _Claude Code on behalf of Federico Mariani_



--
This message was sent by Atlassian Jira
(v8.20.10#820010)