This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-spring-boot.git


The following commit(s) were added to refs/heads/main by this push:
     new 4b978c40359 CAMEL-24757: Improve Spring Cache state store backend 
support (#2046)
4b978c40359 is described below

commit 4b978c40359b5015edce6ef4f7f0579d87162c32
Author: Ramu <[email protected]>
AuthorDate: Wed Oct 21 10:04:43 2026 +0530

    CAMEL-24757: Improve Spring Cache state store backend support (#2046)
    
    * CAMEL-24757: Add Spring Cache-backed KeyValueRepository for 
camel-spring-boot
    
    * CAMEL-24757: Finalize SpringCacheKeyValueRepository and address review 
feedback
    
    - Document @EnableCaching prerequisite and spring.cache.cache-names 
requirement for camel-kvr
    - Explicitly detail cross-EIP auto-discovery side effects 
(AggregateProcessor, IdempotentConsumer, and Cache EIP)
    - Resolve test context runner bean resolution and resource lifecycle 
handling
    - Add configuration metadata for camel.spring.cache.state-store.enabled
    
    * CAMEL-24757: Add Spring Cache-backed KeyValueRepository adapter
    
    * CAMEL-24757: Move Spring Cache state store to starter
    
    * CAMEL-24757: Fix Spring Cache state store Redis tests
    
    * CAMEL-24757: Improve state store backend tests
    
    * CAMEL-24757: Document state store backend choices
    
    * CAMEL-24757: Clarify Spring Cache setup requirements
---
 .../camel-state-store-starter/pom.xml              | 108 ++++++
 .../src/main/doc/limitations.adoc                  |  11 +
 .../src/main/doc/usage.adoc                        |  43 +++
 .../src/main/docs/state-store.json                 |   6 +
 .../cache/SpringCacheKeyValueRepository.java       | 203 ++++++++++
 .../SpringCacheStateStoreAutoConfiguration.java    |  49 +++
 .../additional-spring-configuration-metadata.json  |  10 +
 ...rk.boot.autoconfigure.AutoConfiguration.imports |   1 +
 .../cache/SpringCacheKeyValueRepositoryTest.java   | 407 +++++++++++++++++++++
 ...SpringCacheStateStoreAutoConfigurationTest.java | 337 +++++++++++++++++
 .../cache/SpringCacheStateStoreRedisIT.java        | 185 ++++++++++
 .../src/main/docs/spring-boot.adoc                 |   2 +-
 .../modules/ROOT/pages/starters/state-store.adoc   |  63 +++-
 13 files changed, 1423 insertions(+), 2 deletions(-)

diff --git a/components-starter/camel-state-store-starter/pom.xml 
b/components-starter/camel-state-store-starter/pom.xml
index b8992727974..5fa393787cb 100644
--- a/components-starter/camel-state-store-starter/pom.xml
+++ b/components-starter/camel-state-store-starter/pom.xml
@@ -38,6 +38,39 @@
       <artifactId>camel-state-store</artifactId>
       <version>${camel-version}</version>
     </dependency>
+    <dependency>
+      <groupId>com.github.ben-manes.caffeine</groupId>
+      <artifactId>caffeine</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context-support</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-cache</artifactId>
+      <version>${spring-boot-version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-data-redis</artifactId>
+      <version>${spring-boot-version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-test-infra-redis</artifactId>
+      <version>${camel-version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.awaitility</groupId>
+      <artifactId>awaitility</artifactId>
+      <scope>test</scope>
+    </dependency>
     <!--START OF GENERATED CODE-->
     <dependency>
       <groupId>org.apache.camel.springboot</groupId>
@@ -45,4 +78,79 @@
     </dependency>
     <!--END OF GENERATED CODE-->
   </dependencies>
+  <profiles>
+    <profile>
+      <id>state-store-integration-tests-docker-file</id>
+      <activation>
+        <file>
+          <exists>/var/run/docker.sock</exists>
+        </file>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-failsafe-plugin</artifactId>
+            <executions>
+              <execution>
+                <goals>
+                  <goal>integration-test</goal>
+                  <goal>verify</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <id>state-store-integration-tests-docker-env</id>
+      <activation>
+        <property>
+          <name>env.DOCKER_HOST</name>
+        </property>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-failsafe-plugin</artifactId>
+            <executions>
+              <execution>
+                <goals>
+                  <goal>integration-test</goal>
+                  <goal>verify</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <id>state-store-integration-tests-ci</id>
+      <activation>
+        <property>
+          <name>ci.env.name</name>
+          <value>apache.org</value>
+        </property>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-failsafe-plugin</artifactId>
+            <executions>
+              <execution>
+                <goals>
+                  <goal>integration-test</goal>
+                  <goal>verify</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
 </project>
diff --git 
a/components-starter/camel-state-store-starter/src/main/doc/limitations.adoc 
b/components-starter/camel-state-store-starter/src/main/doc/limitations.adoc
new file mode 100644
index 00000000000..880f77dcb5e
--- /dev/null
+++ b/components-starter/camel-state-store-starter/src/main/doc/limitations.adoc
@@ -0,0 +1,11 @@
+=== Spring Cache
+
+Spring Cache provides a common API, but some operations depend on the 
underlying cache provider.
+
+* **Per-entry TTL:** Spring Cache has no portable per-entry TTL API. A 
positive, non-zero TTL requested through the repository is not applied by the 
Spring adapter. Configure expiration using the underlying cache provider, for 
example with `spring.cache.redis.time-to-live` or a Caffeine specification.
+* **Atomic operations:** Spring Cache does not provide a portable atomic 
get-and-put operation. The adapter's `put` and `delete` read the previous value 
and then write or evict separately, so the returned previous value is not 
atomic. `putIfAbsent` delegates to the provider's Spring Cache implementation; 
its atomicity depends on that provider. Conditional `replace` and conditional 
`delete` may use non-atomic check-then-act operations.
+* **Key enumeration and size:** `keys()` and `size()` are supported only when 
`Cache.getNativeCache()` returns a `ConcurrentMap`, such as with the simple 
cache provider. They operate on a snapshot of current string keys. Other 
providers, including Caffeine, Redis, and JCache, do not support these 
operations through the Spring adapter.
+
+=== Camel KeyValueRepository
+
+Choose a Camel repository when you need capabilities beyond the portable 
Spring Cache API, such as per-entry TTL, atomic `putIfAbsent` or `replace`, 
conditional deletion, and key enumeration or size. Actual support and 
guarantees depend on the selected repository implementation.
diff --git 
a/components-starter/camel-state-store-starter/src/main/doc/usage.adoc 
b/components-starter/camel-state-store-starter/src/main/doc/usage.adoc
new file mode 100644
index 00000000000..b86d9ce7474
--- /dev/null
+++ b/components-starter/camel-state-store-starter/src/main/doc/usage.adoc
@@ -0,0 +1,43 @@
+=== Choosing a backend
+
+The State Store component supports Spring Cache and Camel `KeyValueRepository` 
backends.
+
+==== Spring Cache
+
+Set `camel.state-store.spring-cache.enabled=true` to register a 
`StateStoreBackendFactory` backed by Spring's `CacheManager`. Each state-store 
name maps to a Spring cache with the same name, reusing the application's 
`spring.cache.*` configuration.
+
+The factory is registered when a single `CacheManager` candidate is available 
and no other `StateStoreBackendFactory` bean is defined. It does not register a 
global `KeyValueRepository` bean.
+
+==== Camel KeyValueRepository
+
+Alternatively, use a Camel `KeyValueRepository` implementation, such as 
`camel-redis`, `camel-caffeine`, `camel-jcache`, `camel-sql`, or 
`camel-infinispan`. Define the repository as a bean and leave 
`camel.state-store.spring-cache.enabled` disabled. The State Store component 
automatically discovers the repository.
+
+These repositories can also be discovered by Camel features that support 
`KeyValueRepository`, including the Aggregate EIP, Idempotent Consumer, and 
Cache EIP.
+
+==== Configuration examples
+
+To use Spring Cache, configure a cache provider and enable the factory:
+
+[source,properties]
+----
+spring.cache.type=caffeine
+spring.cache.cache-names=orders,users
+camel.state-store.spring-cache.enabled=true
+----
+
+Spring Boot creates the `CacheManager` from `spring.cache.*` only when the 
application enables caching with `@EnableCaching`; otherwise, provide your own 
`CacheManager` bean. Without a single eligible `CacheManager`, the factory is 
not registered, and stores may fall back to the default in-memory repository. 
If `spring.cache.cache-names` specifies a fixed set of names, include every 
state-store name you use. A dynamic cache manager can create caches on demand.
+
+To use a specific Camel repository, register it as a bean, for example under 
the name `redisRepo`, and select it on the endpoint:
+
+[source,java]
+----
+from("direct:order")
+    .setHeader("CamelStateStoreKey", simple("${header.orderId}"))
+    .to("state-store:orders?backend=#redisRepo");
+----
+
+==== Using both backends
+
+When the Spring Cache factory is enabled, it is the default backend for 
state-store endpoints unless an endpoint explicitly selects another backend or 
a component-level backend factory takes precedence.
+
+You can therefore use Spring Cache for ordinary stores and explicitly select a 
Camel repository for stores that need its additional capabilities.
diff --git 
a/components-starter/camel-state-store-starter/src/main/docs/state-store.json 
b/components-starter/camel-state-store-starter/src/main/docs/state-store.json
index 20f3e7d3ea4..3b4ff143f73 100644
--- 
a/components-starter/camel-state-store-starter/src/main/docs/state-store.json
+++ 
b/components-starter/camel-state-store-starter/src/main/docs/state-store.json
@@ -43,6 +43,12 @@
       "description": "Whether the producer should be started lazy (on the 
first message). By starting lazy you can use this to allow CamelContext and 
routes to startup in situations where a producer may otherwise fail during 
starting and cause the route to fail being started. By deferring this startup 
to be lazy then the startup failure can be handled during routing messages via 
Camel's routing error handlers. Beware that when the first message is processed 
then creating and starting the [...]
       "sourceType": 
"org.apache.camel.component.statestore.springboot.StateStoreComponentConfiguration",
       "defaultValue": false
+    },
+    {
+      "name": "camel.state-store.spring-cache.enabled",
+      "type": "java.lang.Boolean",
+      "description": "Whether to register a StateStoreBackendFactory that 
creates a Spring Cache-backed KeyValueRepository for each state-store name. 
Disabled by default. Requires a single CacheManager bean and no user-defined 
StateStoreBackendFactory. Does not register a global KeyValueRepository.",
+      "defaultValue": false
     }
   ],
   "hints": [],
diff --git 
a/components-starter/camel-state-store-starter/src/main/java/org/apache/camel/component/statestore/springboot/cache/SpringCacheKeyValueRepository.java
 
b/components-starter/camel-state-store-starter/src/main/java/org/apache/camel/component/statestore/springboot/cache/SpringCacheKeyValueRepository.java
new file mode 100644
index 00000000000..a9f9a5d4429
--- /dev/null
+++ 
b/components-starter/camel-state-store-starter/src/main/java/org/apache/camel/component/statestore/springboot/cache/SpringCacheKeyValueRepository.java
@@ -0,0 +1,203 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.statestore.springboot.cache;
+
+import java.time.Duration;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.camel.spi.KeyValueRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.concurrent.ConcurrentMapCache;
+import org.springframework.util.Assert;
+
+/**
+ * An Apache Camel {@link KeyValueRepository} adapter backed by Spring's
+ * {@link CacheManager}. Each instance is bound to one Spring cache whose name
+ * matches the Camel state-store name.
+ * <h3>Design Constraints and Backend Behavior</h3>
+ * <ul>
+ *   <li><strong>TTL support:</strong> Spring Cache does not define a standard
+ *       per-entry TTL API. A positive, non-zero TTL triggers a single
+ *       {@code WARN} log per repository instance. The entry is stored without
+ *       applying the requested TTL. {@code null}, zero, and negative TTL 
values
+ *       do not trigger this warning or consume the warning-once guard. Users
+ *       requiring expiration must configure it through the underlying cache
+ *       provider or {@link CacheManager}, for example using a Caffeine cache
+ *       specification.</li>
+ *   <li><strong>Atomicity:</strong> Spring Cache has no atomic get-and-put
+ *       API. {@code put} and {@code delete} read the previous value and then
+ *       write or evict in a second call, so the returned old value is not
+ *       atomic. {@code putIfAbsent} delegates to
+ *       {@link Cache#putIfAbsent(Object, Object)}, whose atomicity depends on
+ *       the provider. Conditional operations such as {@code replace} and
+ *       conditional {@code delete} use the {@link KeyValueRepository} SPI
+ *       default implementations and may perform non-atomic check-then-act
+ *       operations.</li>
+ *   <li><strong>Enumeration:</strong> {@link #keys()} and {@link #size()} are
+ *       supported only when {@link Cache#getNativeCache()} is a
+ *       {@link ConcurrentMap}, for example {@link ConcurrentMapCache}. They
+ *       operate on a snapshot of current {@link String} keys; {@link #size()}
+ *       is the size of that snapshot, and non-{@link String} native keys are
+ *       ignored. Other native cache types throw
+ *       {@link UnsupportedOperationException} from {@link #keys()} and
+ *       {@link #size()} only; {@code get}, {@code put}, {@code delete}, and
+ *       related operations still delegate to Spring Cache. Spring's Caffeine,
+ *       Redis, and JCache adapters do not return a {@code ConcurrentMap} from
+ *       {@code getNativeCache()}, so enumeration is unsupported for those
+ *       backends. When this adapter is bound explicitly, Camel operations that
+ *       enumerate keys (Aggregate recovery, {@code completionTimeout} restore
+ *       via {@code getKeys()}, and Idempotent Consumer {@code clear()})
+ *       therefore require a {@code ConcurrentMap} native cache.</li>
+ *   <li><strong>Scope:</strong> The repository is bound to the cache named by
+ *       the constructor. {@link #clear()} invalidates that entire cache. Use a
+ *       distinct store name (and therefore cache name) for each isolated
+ *       store.</li>
+ * </ul>
+ */
+public class SpringCacheKeyValueRepository implements KeyValueRepository {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(SpringCacheKeyValueRepository.class);
+    private static final String ENUMERATION_UNSUPPORTED
+            = "Spring Cache does not provide a portable key enumeration API; 
keys() and size() are supported only when Cache.getNativeCache() is a 
ConcurrentMap.";
+
+    private final CacheManager cacheManager;
+    private final String cacheName;
+    private final AtomicBoolean ttlWarningLogged = new AtomicBoolean(false);
+
+    public SpringCacheKeyValueRepository(CacheManager cacheManager, String 
cacheName) {
+        Assert.notNull(cacheManager, "CacheManager must not be null");
+        Assert.hasText(cacheName, "CacheName must not be empty");
+        this.cacheManager = cacheManager;
+        this.cacheName = cacheName;
+    }
+
+    public String getCacheName() {
+        return cacheName;
+    }
+
+    private Cache getCache() {
+        Cache cache = cacheManager.getCache(cacheName);
+        if (cache == null) {
+            throw new IllegalStateException(String.format("Spring Cache '%s' 
not found in CacheManager of type %s",
+                    cacheName, cacheManager.getClass().getName()));
+        }
+        return cache;
+    }
+
+    @Override
+    public void start() {
+        // Lifecycle start hook (managed externally by Spring CacheManager 
container)
+    }
+
+    @Override
+    public void stop() {
+        // Lifecycle stop hook (managed externally by Spring CacheManager 
container)
+    }
+
+    @Override
+    public Object get(String key) {
+        Cache.ValueWrapper wrapper = getCache().get(key);
+        return wrapper != null ? wrapper.get() : null;
+    }
+
+    @Override
+    public Object put(String key, Object value) {
+        return put(key, value, null);
+    }
+
+    @Override
+    public Object put(String key, Object value, Duration ttl) {
+        checkTtl(ttl);
+        Cache cache = getCache();
+        Cache.ValueWrapper oldWrapper = cache.get(key);
+        Object oldValue = oldWrapper != null ? oldWrapper.get() : null;
+        cache.put(key, value);
+        return oldValue;
+    }
+
+    @Override
+    public Object putIfAbsent(String key, Object value) {
+        return putIfAbsent(key, value, null);
+    }
+
+    @Override
+    public Object putIfAbsent(String key, Object value, Duration ttl) {
+        checkTtl(ttl);
+        Cache.ValueWrapper existing = getCache().putIfAbsent(key, value);
+        return existing != null ? existing.get() : null;
+    }
+
+    @Override
+    public Object delete(String key) {
+        Cache cache = getCache();
+        Cache.ValueWrapper oldWrapper = cache.get(key);
+        Object oldValue = oldWrapper != null ? oldWrapper.get() : null;
+        cache.evictIfPresent(key);
+        return oldValue;
+    }
+
+    @Override
+    public boolean contains(String key) {
+        return getCache().get(key) != null;
+    }
+
+    @Override
+    public void clear() {
+        Cache cache = getCache();
+        cache.invalidate();
+    }
+
+    @Override
+    public Set<String> keys() {
+        return Collections.unmodifiableSet(snapshotStringKeys());
+    }
+
+    @Override
+    public int size() {
+        return snapshotStringKeys().size();
+    }
+
+    private Set<String> snapshotStringKeys() {
+        Object nativeCache = getCache().getNativeCache();
+        if (!(nativeCache instanceof ConcurrentMap<?, ?> concurrentMap)) {
+            throw new UnsupportedOperationException(ENUMERATION_UNSUPPORTED);
+        }
+        Set<String> snapshot = new HashSet<>();
+        for (Object key : concurrentMap.keySet()) {
+            if (key instanceof String stringKey) {
+                snapshot.add(stringKey);
+            }
+        }
+        return snapshot;
+    }
+
+    private void checkTtl(Duration ttl) {
+        if (ttl != null && !ttl.isNegative() && !ttl.isZero()) {
+            if (ttlWarningLogged.compareAndSet(false, true)) {
+                LOG.warn("Per-entry TTL of {} is not supported by the Spring 
Cache backend for store '{}'; storing without expiration.",
+                        ttl, cacheName);
+            }
+        }
+    }
+}
diff --git 
a/components-starter/camel-state-store-starter/src/main/java/org/apache/camel/component/statestore/springboot/cache/SpringCacheStateStoreAutoConfiguration.java
 
b/components-starter/camel-state-store-starter/src/main/java/org/apache/camel/component/statestore/springboot/cache/SpringCacheStateStoreAutoConfiguration.java
new file mode 100644
index 00000000000..a8720f3d4f6
--- /dev/null
+++ 
b/components-starter/camel-state-store-starter/src/main/java/org/apache/camel/component/statestore/springboot/cache/SpringCacheStateStoreAutoConfiguration.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.statestore.springboot.cache;
+
+import org.apache.camel.component.statestore.StateStoreBackendFactory;
+import org.apache.camel.spi.KeyValueRepository;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import 
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import 
org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
+import org.springframework.cache.CacheManager;
+import org.springframework.context.annotation.Bean;
+
+/**
+ * Opt-in auto-configuration that registers a {@link StateStoreBackendFactory}
+ * backed by Spring Cache. Disabled unless
+ * {@code camel.state-store.spring-cache.enabled=true}. The factory creates one
+ * {@link SpringCacheKeyValueRepository} per state-store name and does not
+ * register a global {@link KeyValueRepository} bean.
+ */
+@AutoConfiguration(after = CamelAutoConfiguration.class,
+        afterName = 
"org.springframework.boot.cache.autoconfigure.CacheAutoConfiguration")
+@ConditionalOnClass({ CacheManager.class, StateStoreBackendFactory.class })
+@ConditionalOnProperty(prefix = "camel.state-store.spring-cache", name = 
"enabled", havingValue = "true")
+public class SpringCacheStateStoreAutoConfiguration {
+
+    @Bean
+    @ConditionalOnSingleCandidate(CacheManager.class)
+    @ConditionalOnMissingBean(StateStoreBackendFactory.class)
+    public StateStoreBackendFactory 
springCacheStateStoreBackendFactory(CacheManager cacheManager) {
+        return storeName -> new SpringCacheKeyValueRepository(cacheManager, 
storeName);
+    }
+}
diff --git 
a/components-starter/camel-state-store-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json
 
b/components-starter/camel-state-store-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json
new file mode 100644
index 00000000000..2e72f1239d6
--- /dev/null
+++ 
b/components-starter/camel-state-store-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -0,0 +1,10 @@
+{
+  "properties": [
+    {
+      "name": "camel.state-store.spring-cache.enabled",
+      "type": "java.lang.Boolean",
+      "description": "Whether to register a StateStoreBackendFactory that 
creates a Spring Cache-backed KeyValueRepository for each state-store name. 
Disabled by default. Requires a single CacheManager bean and no user-defined 
StateStoreBackendFactory. Does not register a global KeyValueRepository.",
+      "defaultValue": false
+    }
+  ]
+}
diff --git 
a/components-starter/camel-state-store-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
 
b/components-starter/camel-state-store-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index b4d44e5a8ff..aad76b7df12 100644
--- 
a/components-starter/camel-state-store-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ 
b/components-starter/camel-state-store-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -16,3 +16,4 @@
 ## ---------------------------------------------------------------------------
 
org.apache.camel.component.statestore.springboot.StateStoreComponentAutoConfiguration
 org.apache.camel.component.statestore.springboot.StateStoreComponentConverter
+org.apache.camel.component.statestore.springboot.cache.SpringCacheStateStoreAutoConfiguration
diff --git 
a/components-starter/camel-state-store-starter/src/test/java/org/apache/camel/component/statestore/springboot/cache/SpringCacheKeyValueRepositoryTest.java
 
b/components-starter/camel-state-store-starter/src/test/java/org/apache/camel/component/statestore/springboot/cache/SpringCacheKeyValueRepositoryTest.java
new file mode 100644
index 00000000000..aa86a491b90
--- /dev/null
+++ 
b/components-starter/camel-state-store-starter/src/test/java/org/apache/camel/component/statestore/springboot/cache/SpringCacheKeyValueRepositoryTest.java
@@ -0,0 +1,407 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.statestore.springboot.cache;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.AppenderBase;
+
+import org.apache.camel.spi.KeyValueRepository;
+import org.junit.jupiter.api.Test;
+import org.slf4j.LoggerFactory;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.caffeine.CaffeineCacheManager;
+import org.springframework.cache.concurrent.ConcurrentMapCache;
+import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
+import org.springframework.cache.support.SimpleCacheManager;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+class SpringCacheKeyValueRepositoryTest {
+
+    @Test
+    void shouldHandleCrudLifecycleAndReturnValues() {
+        CacheManager cacheManager = new ConcurrentMapCacheManager("orders");
+        SpringCacheKeyValueRepository repo = new 
SpringCacheKeyValueRepository(cacheManager, "orders");
+        assertThat(repo.contains("key1")).isFalse();
+        assertThat(repo.get("key1")).isNull();
+
+        Object previous = repo.put("key1", "val1");
+        assertThat(previous).isNull();
+        assertThat(repo.contains("key1")).isTrue();
+        assertThat(repo.get("key1")).isEqualTo("val1");
+
+        Object updatedPrevious = repo.put("key1", "val2");
+        assertThat(updatedPrevious).isEqualTo("val1");
+        assertThat(repo.get("key1")).isEqualTo("val2");
+
+        Object deletedValue = repo.delete("key1");
+        assertThat(deletedValue).isEqualTo("val2");
+        assertThat(repo.contains("key1")).isFalse();
+
+        assertThat(repo.delete("non-existent")).isNull();
+    }
+
+    @Test
+    void shouldHandlePutIfAbsent() {
+        CacheManager cacheManager = new ConcurrentMapCacheManager("orders");
+        SpringCacheKeyValueRepository repo = new 
SpringCacheKeyValueRepository(cacheManager, "orders");
+        Object existing1 = repo.putIfAbsent("key1", "val1");
+        assertThat(existing1).isNull();
+        assertThat(repo.get("key1")).isEqualTo("val1");
+
+        Object existing2 = repo.putIfAbsent("key1", "newVal");
+        assertThat(existing2).isEqualTo("val1");
+        assertThat(repo.get("key1")).isEqualTo("val1");
+    }
+
+    @Test
+    void shouldClearOnlyTheNamedCache() {
+        CacheManager cacheManager = new ConcurrentMapCacheManager("orders");
+        SpringCacheKeyValueRepository repo = new 
SpringCacheKeyValueRepository(cacheManager, "orders");
+        repo.put("key1", "val1");
+        repo.put("key2", "val2");
+        repo.clear();
+
+        assertThat(repo.contains("key1")).isFalse();
+        assertThat(repo.contains("key2")).isFalse();
+    }
+
+    @Test
+    void shouldSupportInheritedConditionalOperations() {
+        CacheManager cacheManager = new ConcurrentMapCacheManager("orders");
+        SpringCacheKeyValueRepository repo = new 
SpringCacheKeyValueRepository(cacheManager, "orders");
+        repo.put("key1", "val1");
+
+        boolean replaced = repo.replace("key1", "val1", "val2", null);
+        assertThat(replaced).isTrue();
+        assertThat(repo.get("key1")).isEqualTo("val2");
+
+        boolean deletedMismatch = repo.delete("key1", "wrongVal");
+        assertThat(deletedMismatch).isFalse();
+        assertThat(repo.contains("key1")).isTrue();
+
+        boolean deletedMatch = repo.delete("key1", "val2");
+        assertThat(deletedMatch).isTrue();
+        assertThat(repo.contains("key1")).isFalse();
+    }
+
+    @Test
+    void shouldThrowWhenNamedCacheIsMissing() {
+        SimpleCacheManager strictCacheManager = new SimpleCacheManager();
+        strictCacheManager.setCaches(Collections.singletonList(new 
ConcurrentMapCache("other-cache")));
+        strictCacheManager.initializeCaches();
+
+        SpringCacheKeyValueRepository repo = new 
SpringCacheKeyValueRepository(strictCacheManager, "orders");
+        assertThatThrownBy(() -> repo.get("key1"))
+                .isInstanceOf(IllegalStateException.class)
+                .hasMessageContaining("Spring Cache 'orders' not found in 
CacheManager");
+    }
+
+    @Test
+    void shouldEnumerateKeysAndSizeForConcurrentMapNativeCache() {
+        CacheManager cacheManager = new ConcurrentMapCacheManager("orders");
+        SpringCacheKeyValueRepository repo = new 
SpringCacheKeyValueRepository(cacheManager, "orders");
+        repo.put("key1", "val1");
+        repo.put("key2", "val2");
+
+        Cache cache = cacheManager.getCache("orders");
+        assertThat(cache).isNotNull();
+        assertThat(cache.getNativeCache()).isInstanceOf(ConcurrentMap.class);
+        cache.put(42, "non-string-key");
+
+        Set<String> keys = repo.keys();
+        assertThat(keys).containsExactlyInAnyOrder("key1", "key2");
+        assertThat(repo.size()).isEqualTo(2);
+        assertThat(repo.size()).isEqualTo(keys.size());
+
+        repo.put("key3", "val3");
+        assertThat(keys).doesNotContain("key3");
+        assertThat(keys).isUnmodifiable();
+        assertThat(repo.keys()).containsExactlyInAnyOrder("key1", "key2", 
"key3");
+        assertThat(repo.size()).isEqualTo(3);
+    }
+
+    @Test
+    void shouldThrowUnsupportedForKeysAndSizeWithRealCaffeineCache() {
+        CaffeineCacheManager cacheManager = new CaffeineCacheManager("orders");
+        KeyValueRepository repo = new 
SpringCacheKeyValueRepository(cacheManager, "orders");
+        repo.put("key1", "val1");
+
+        Cache cache = cacheManager.getCache("orders");
+        assertThat(cache).isNotNull();
+        
assertThat(cache.getNativeCache()).isNotInstanceOf(ConcurrentMap.class);
+        assertThat(repo.get("key1")).isEqualTo("val1");
+
+        assertThatThrownBy(repo::keys)
+                .isInstanceOf(UnsupportedOperationException.class)
+                .hasMessageContaining("ConcurrentMap");
+        assertThatThrownBy(repo::size)
+                .isInstanceOf(UnsupportedOperationException.class)
+                .hasMessageContaining("ConcurrentMap");
+    }
+
+    @Test
+    void 
shouldThrowUnsupportedForKeysAndSizeWhenNativeCacheIsNotConcurrentMap() {
+        CacheManager cacheManager = new SingleCacheManager(new 
NonConcurrentNativeCache("orders"));
+        KeyValueRepository repo = new 
SpringCacheKeyValueRepository(cacheManager, "orders");
+        repo.put("key1", "val1");
+
+        assertThatThrownBy(repo::keys)
+                .isInstanceOf(UnsupportedOperationException.class)
+                .hasMessageContaining("portable key enumeration API")
+                .hasMessageContaining("ConcurrentMap");
+
+        assertThatThrownBy(repo::size)
+                .isInstanceOf(UnsupportedOperationException.class)
+                .hasMessageContaining("portable key enumeration API")
+                .hasMessageContaining("ConcurrentMap");
+
+        assertThat(repo.get("key1")).isEqualTo("val1");
+    }
+
+    @Test
+    void shouldStoreEntriesWhenTtlIsPositiveWithoutApplyingExpiration() {
+        CacheManager cacheManager = new ConcurrentMapCacheManager("orders");
+        SpringCacheKeyValueRepository repo = new 
SpringCacheKeyValueRepository(cacheManager, "orders");
+        repo.put("k1", "v1", Duration.ofMinutes(5));
+        repo.putIfAbsent("k2", "v2", Duration.ofMinutes(10));
+        repo.put("k1", "v3", Duration.ofMinutes(2));
+
+        assertThat(repo.get("k1")).isEqualTo("v3");
+        assertThat(repo.get("k2")).isEqualTo("v2");
+    }
+
+    @Test
+    void shouldMaintainIsolationBetweenStoreNames() {
+        CacheManager cacheManager = new ConcurrentMapCacheManager("orders", 
"users");
+        SpringCacheKeyValueRepository orders = new 
SpringCacheKeyValueRepository(cacheManager, "orders");
+        SpringCacheKeyValueRepository users = new 
SpringCacheKeyValueRepository(cacheManager, "users");
+
+        orders.put("id", "ORDER_PLACED");
+        users.put("id", "IN_STOCK");
+
+        assertThat(orders.get("id")).isEqualTo("ORDER_PLACED");
+        assertThat(users.get("id")).isEqualTo("IN_STOCK");
+
+        orders.clear();
+
+        assertThat(orders.contains("id")).isFalse();
+        assertThat(users.contains("id")).isTrue();
+    }
+
+    @Test
+    void ttlWarningLoggedOnlyOncePerRepositoryInstance() {
+        String cacheName = uniqueCacheName();
+        Logger logger = (Logger) 
LoggerFactory.getLogger(SpringCacheKeyValueRepository.class);
+        ThreadSafeTestAppender appender = attachAppender(logger);
+
+        try {
+            CacheManager cacheManager = new 
ConcurrentMapCacheManager(cacheName);
+            KeyValueRepository first = new 
SpringCacheKeyValueRepository(cacheManager, cacheName);
+            KeyValueRepository second = new 
SpringCacheKeyValueRepository(cacheManager, cacheName);
+
+            first.put("key1", "value1", Duration.ofSeconds(10));
+            first.put("key2", "value2", Duration.ofSeconds(20));
+            second.put("key3", "value3", Duration.ofSeconds(10));
+
+            assertThat(ttlWarningCount(appender.getEvents(), 
cacheName)).isEqualTo(2);
+        } finally {
+            detachAppender(logger, appender);
+        }
+    }
+
+    @Test
+    void nonPositiveTtlShouldNotTriggerWarningOrConsumeGuard() {
+        String cacheName = uniqueCacheName();
+        Logger logger = (Logger) 
LoggerFactory.getLogger(SpringCacheKeyValueRepository.class);
+        ThreadSafeTestAppender appender = attachAppender(logger);
+
+        try {
+            CacheManager cacheManager = new 
ConcurrentMapCacheManager(cacheName);
+            KeyValueRepository repository = new 
SpringCacheKeyValueRepository(cacheManager, cacheName);
+
+            repository.put("key-null", "value", null);
+            repository.put("key-zero", "value", Duration.ZERO);
+            repository.put("key-negative", "value", Duration.ofSeconds(-5));
+
+            assertThat(ttlWarningCount(appender.getEvents(), 
cacheName)).isZero();
+
+            repository.put("key-positive", "value", Duration.ofSeconds(10));
+
+            assertThat(ttlWarningCount(appender.getEvents(), 
cacheName)).isEqualTo(1);
+        } finally {
+            detachAppender(logger, appender);
+        }
+    }
+
+    private String uniqueCacheName() {
+        return "ttl-warning-test-" + UUID.randomUUID();
+    }
+
+    private ThreadSafeTestAppender attachAppender(Logger logger) {
+        ThreadSafeTestAppender appender = new ThreadSafeTestAppender();
+        appender.setContext(logger.getLoggerContext());
+        appender.start();
+        logger.addAppender(appender);
+        return appender;
+    }
+
+    private void detachAppender(Logger logger, ThreadSafeTestAppender 
appender) {
+        logger.detachAppender(appender);
+        appender.stop();
+    }
+
+    private long ttlWarningCount(List<ILoggingEvent> events, String cacheName) 
{
+        List<ILoggingEvent> snapshot = new ArrayList<>(events);
+        String expectedStore = "store '" + cacheName + "'";
+
+        return snapshot.stream()
+                .filter(event -> event.getLevel() == Level.WARN)
+                .filter(event -> 
SpringCacheKeyValueRepository.class.getName().equals(event.getLoggerName()))
+                .filter(event -> 
event.getFormattedMessage().contains("Per-entry TTL"))
+                .filter(event -> 
event.getFormattedMessage().contains(expectedStore))
+                .count();
+    }
+
+    static final class ThreadSafeTestAppender extends 
AppenderBase<ILoggingEvent> {
+        private final List<ILoggingEvent> events = new 
CopyOnWriteArrayList<>();
+
+        @Override
+        protected void append(ILoggingEvent eventObject) {
+            events.add(eventObject);
+        }
+
+        public List<ILoggingEvent> getEvents() {
+            return events;
+        }
+    }
+
+    static final class NonConcurrentNativeCache implements Cache {
+        private final String name;
+        private final Map<Object, Object> store = new HashMap<>();
+
+        NonConcurrentNativeCache(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public Object getNativeCache() {
+            return this;
+        }
+
+        @Override
+        public ValueWrapper get(Object key) {
+            if (!store.containsKey(key)) {
+                return null;
+            }
+            Object value = store.get(key);
+            return () -> value;
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public <T> T get(Object key, Class<T> type) {
+            Object value = store.get(key);
+            if (value != null && type != null && !type.isInstance(value)) {
+                throw new IllegalStateException("Cached value is not of 
required type [" + type.getName() + "]: " + value);
+            }
+            return (T) value;
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public <T> T get(Object key, Callable<T> valueLoader) {
+            if (store.containsKey(key)) {
+                return (T) store.get(key);
+            }
+            try {
+                T value = valueLoader.call();
+                store.put(key, value);
+                return value;
+            } catch (Exception ex) {
+                throw new ValueRetrievalException(key, valueLoader, ex);
+            }
+        }
+
+        @Override
+        public void put(Object key, Object value) {
+            store.put(key, value);
+        }
+
+        @Override
+        public void evict(Object key) {
+            store.remove(key);
+        }
+
+        @Override
+        public boolean evictIfPresent(Object key) {
+            return store.remove(key) != null;
+        }
+
+        @Override
+        public void clear() {
+            store.clear();
+        }
+
+        @Override
+        public boolean invalidate() {
+            boolean hadEntries = !store.isEmpty();
+            store.clear();
+            return hadEntries;
+        }
+    }
+
+    static final class SingleCacheManager implements CacheManager {
+        private final Cache cache;
+
+        SingleCacheManager(Cache cache) {
+            this.cache = cache;
+        }
+
+        @Override
+        public Cache getCache(String name) {
+            return cache.getName().equals(name) ? cache : null;
+        }
+
+        @Override
+        public Collection<String> getCacheNames() {
+            return Collections.singleton(cache.getName());
+        }
+    }
+}
diff --git 
a/components-starter/camel-state-store-starter/src/test/java/org/apache/camel/component/statestore/springboot/cache/SpringCacheStateStoreAutoConfigurationTest.java
 
b/components-starter/camel-state-store-starter/src/test/java/org/apache/camel/component/statestore/springboot/cache/SpringCacheStateStoreAutoConfigurationTest.java
new file mode 100644
index 00000000000..15b86585c46
--- /dev/null
+++ 
b/components-starter/camel-state-store-starter/src/test/java/org/apache/camel/component/statestore/springboot/cache/SpringCacheStateStoreAutoConfigurationTest.java
@@ -0,0 +1,337 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.statestore.springboot.cache;
+
+import java.time.Duration;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.statestore.StateStoreBackendFactory;
+import org.apache.camel.component.statestore.StateStoreComponent;
+import org.apache.camel.component.statestore.StateStoreConstants;
+import 
org.apache.camel.component.statestore.springboot.StateStoreComponentAutoConfiguration;
+import 
org.apache.camel.component.statestore.springboot.StateStoreComponentConverter;
+import org.apache.camel.processor.aggregate.UseLatestAggregationStrategy;
+import org.apache.camel.spi.KeyValueRepository;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.support.MemoryKeyValueRepository;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.awaitility.Awaitility.await;
+
+class SpringCacheStateStoreAutoConfigurationTest {
+
+    private final ApplicationContextRunner contextRunner = new 
ApplicationContextRunner()
+            
.withConfiguration(AutoConfigurations.of(SpringCacheStateStoreAutoConfiguration.class))
+            .withPropertyValues("spring.main.banner-mode=off");
+
+    private final ApplicationContextRunner camelRunner = new 
ApplicationContextRunner()
+            .withConfiguration(AutoConfigurations.of(
+                    CamelAutoConfiguration.class,
+                    StateStoreComponentAutoConfiguration.class,
+                    SpringCacheStateStoreAutoConfiguration.class))
+            .withUserConfiguration(StateStoreComponentConverter.class)
+            .withPropertyValues("spring.main.banner-mode=off");
+
+    private final ApplicationContextRunner mixedBackendRunner = new 
ApplicationContextRunner()
+            .withConfiguration(AutoConfigurations.of(
+                    CamelAutoConfiguration.class,
+                    StateStoreComponentAutoConfiguration.class,
+                    SpringCacheStateStoreAutoConfiguration.class))
+            .withUserConfiguration(StateStoreComponentConverter.class)
+            .withBean(CacheManager.class, ConcurrentMapCacheManager::new)
+            .withBean("camelRepo", MemoryKeyValueRepository.class, 
MemoryKeyValueRepository::new)
+            .withPropertyValues("spring.main.banner-mode=off");
+
+    @Test
+    void doesNotRegisterFactoryWhenPropertyIsAbsent() {
+        contextRunner
+                .withBean("cacheManager", CacheManager.class, 
ConcurrentMapCacheManager::new)
+                .run(context -> {
+                    
assertThat(context).doesNotHaveBean(SpringCacheStateStoreAutoConfiguration.class);
+                    
assertThat(context).doesNotHaveBean(StateStoreBackendFactory.class);
+                    
assertThat(context).doesNotHaveBean(KeyValueRepository.class);
+                });
+    }
+
+    @Test
+    void doesNotRegisterFactoryWhenPropertyIsFalse() {
+        contextRunner
+                .withBean("cacheManager", CacheManager.class, 
ConcurrentMapCacheManager::new)
+                
.withPropertyValues("camel.state-store.spring-cache.enabled=false")
+                .run(context -> {
+                    
assertThat(context).doesNotHaveBean(StateStoreBackendFactory.class);
+                    
assertThat(context).doesNotHaveBean(KeyValueRepository.class);
+                });
+    }
+
+    @Test
+    void doesNotRegisterFactoryWhenCacheManagerIsAbsent() {
+        contextRunner
+                
.withPropertyValues("camel.state-store.spring-cache.enabled=true")
+                .run(context -> {
+                    
assertThat(context).doesNotHaveBean(StateStoreBackendFactory.class);
+                    
assertThat(context).doesNotHaveBean(KeyValueRepository.class);
+                });
+    }
+
+    @Test
+    void registersFactoryWhenEnabledWithSingleCacheManager() {
+        contextRunner
+                .withBean("cacheManager", CacheManager.class, 
ConcurrentMapCacheManager::new)
+                
.withPropertyValues("camel.state-store.spring-cache.enabled=true")
+                .run(context -> {
+                    
assertThat(context).hasSingleBean(StateStoreBackendFactory.class);
+                    
assertThat(context).doesNotHaveBean(KeyValueRepository.class);
+
+                    StateStoreBackendFactory factory = 
context.getBean(StateStoreBackendFactory.class);
+                    KeyValueRepository repository = 
factory.createBackend("orders");
+                    
assertThat(repository).isInstanceOf(SpringCacheKeyValueRepository.class);
+                    assertThat(((SpringCacheKeyValueRepository) 
repository).getCacheName()).isEqualTo("orders");
+                });
+    }
+
+    @Test
+    void doesNotRegisterFactoryWhenMultipleCacheManagersPresent() {
+        contextRunner
+                .withBean("cacheManagerOne", CacheManager.class, 
ConcurrentMapCacheManager::new)
+                .withBean("cacheManagerTwo", CacheManager.class, 
ConcurrentMapCacheManager::new)
+                
.withPropertyValues("camel.state-store.spring-cache.enabled=true")
+                .run(context -> {
+                    
assertThat(context.getBeansOfType(CacheManager.class)).hasSize(2);
+                    
assertThat(context).doesNotHaveBean(StateStoreBackendFactory.class);
+                    
assertThat(context).doesNotHaveBean(KeyValueRepository.class);
+                });
+    }
+
+    @Test
+    void backsOffWhenCustomFactoryExists() {
+        StateStoreBackendFactory customFactory = storeName -> new 
MemoryKeyValueRepository();
+        contextRunner
+                .withBean("cacheManager", CacheManager.class, 
ConcurrentMapCacheManager::new)
+                .withBean("customFactory", StateStoreBackendFactory.class, () 
-> customFactory)
+                
.withPropertyValues("camel.state-store.spring-cache.enabled=true")
+                .run(context -> {
+                    
assertThat(context).hasSingleBean(StateStoreBackendFactory.class);
+                    
assertThat(context.getBean(StateStoreBackendFactory.class)).isSameAs(customFactory);
+                    
assertThat(context.getBean(StateStoreBackendFactory.class).createBackend("orders"))
+                            .isInstanceOf(MemoryKeyValueRepository.class);
+                    
assertThat(context).doesNotHaveBean(KeyValueRepository.class);
+                });
+    }
+
+    @Test
+    void createsIndependentRepositoriesPerStoreName() {
+        contextRunner
+                .withBean("cacheManager", CacheManager.class, 
ConcurrentMapCacheManager::new)
+                
.withPropertyValues("camel.state-store.spring-cache.enabled=true")
+                .run(context -> {
+                    StateStoreBackendFactory factory = 
context.getBean(StateStoreBackendFactory.class);
+                    KeyValueRepository orders = 
factory.createBackend("orders");
+                    KeyValueRepository users = factory.createBackend("users");
+
+                    assertThat(((SpringCacheKeyValueRepository) 
orders).getCacheName()).isEqualTo("orders");
+                    assertThat(((SpringCacheKeyValueRepository) 
users).getCacheName()).isEqualTo("users");
+
+                    orders.put("id", "order-1");
+                    users.put("id", "user-1");
+
+                    assertThat(orders.get("id")).isEqualTo("order-1");
+                    assertThat(users.get("id")).isEqualTo("user-1");
+
+                    orders.clear();
+                    assertThat(orders.contains("id")).isFalse();
+                    assertThat(users.get("id")).isEqualTo("user-1");
+                });
+    }
+
+    @Test
+    void doesNotExposeGlobalRepositoryToUnrelatedEips() {
+        camelRunner
+                .withBean("cacheManager", CacheManager.class, 
ConcurrentMapCacheManager::new)
+                
.withPropertyValues("camel.state-store.spring-cache.enabled=true")
+                .run(context -> {
+                    
assertThat(context).hasSingleBean(StateStoreBackendFactory.class);
+                    
assertThat(context).doesNotHaveBean(KeyValueRepository.class);
+
+                    CamelContext camelContext = 
context.getBean(CamelContext.class);
+                    
assertThat(camelContext.getRegistry().findSingleByType(KeyValueRepository.class)).isNull();
+                    
assertThat(camelContext.getRegistry().findByType(KeyValueRepository.class)).isEmpty();
+
+                    StateStoreComponent component = 
camelContext.getComponent("state-store", StateStoreComponent.class);
+                    assertThat(component.getBackendFactory())
+                            
.isSameAs(context.getBean(StateStoreBackendFactory.class));
+
+                    ProducerTemplate template = 
camelContext.createProducerTemplate();
+                    try {
+                        
template.requestBodyAndHeader("state-store:orders?operation=put", "order-1",
+                                StateStoreConstants.KEY, "id");
+                        
template.requestBodyAndHeader("state-store:users?operation=put", "user-1",
+                                StateStoreConstants.KEY, "id");
+
+                        
assertThat(template.requestBodyAndHeader("state-store:orders?operation=get", 
null,
+                                StateStoreConstants.KEY, 
"id")).isEqualTo("order-1");
+                        
assertThat(template.requestBodyAndHeader("state-store:users?operation=get", 
null,
+                                StateStoreConstants.KEY, 
"id")).isEqualTo("user-1");
+                    } finally {
+                        template.stop();
+                    }
+
+                    CacheManager cacheManager = 
context.getBean(CacheManager.class);
+                    
assertThat(cacheManager.getCache("orders").get("id").get()).isEqualTo("order-1");
+                    
assertThat(cacheManager.getCache("users").get("id").get()).isEqualTo("user-1");
+                });
+    }
+
+    @Test
+    void springFactoryAndCamelRepositoryCoexist() {
+        mixedBackendRunner
+                
.withPropertyValues("camel.state-store.spring-cache.enabled=true")
+                .run(ctx -> {
+                    ProducerTemplate template = 
ctx.getBean(CamelContext.class).createProducerTemplate();
+                    try {
+                        
template.sendBodyAndHeader("state-store:orders?operation=put", "o1",
+                                StateStoreConstants.KEY, "1");
+                        
template.sendBodyAndHeader("state-store:sessions?operation=put&backend=#camelRepo",
 "s1",
+                                StateStoreConstants.KEY, "1");
+
+                        
assertThat(ctx.getBean(CacheManager.class).getCache("orders").get("1").get())
+                                .isEqualTo("o1");
+                        assertThat(ctx.getBean("camelRepo", 
MemoryKeyValueRepository.class).get("1"))
+                                .isEqualTo("s1");
+                        
assertThat(ctx.getBean(CacheManager.class).getCache("sessions").get("1")).isNull();
+                    } finally {
+                        template.stop();
+                    }
+                });
+    }
+
+    @Test
+    void camelRepositoryIsUsedWhenSpringCacheIsDisabled() {
+        mixedBackendRunner.run(ctx -> {
+            ProducerTemplate template = 
ctx.getBean(CamelContext.class).createProducerTemplate();
+            try {
+                template.sendBodyAndHeader("state-store:orders?operation=put", 
"o1",
+                        StateStoreConstants.KEY, "1");
+
+                assertThat(ctx.getBean("camelRepo", 
MemoryKeyValueRepository.class).get("1")).isEqualTo("o1");
+            } finally {
+                template.stop();
+            }
+        });
+    }
+
+    @Test
+    void optimisticLockingAggregatorStartsWhenFactoryEnabled() {
+        camelRunner
+                .withBean("cacheManager", CacheManager.class, 
ConcurrentMapCacheManager::new)
+                .withBean(RouteBuilder.class, this::optimisticLockingRoute)
+                
.withPropertyValues("camel.state-store.spring-cache.enabled=true")
+                .run(context -> {
+                    assertThat(context).hasNotFailed();
+                    
assertThat(context).doesNotHaveBean(KeyValueRepository.class);
+                    CamelContext camelContext = 
context.getBean(CamelContext.class);
+                    assertThat(camelContext.getStatus().isStarted()).isTrue();
+                    assertThat(camelContext.getRoute("agg")).isNotNull();
+                });
+    }
+
+    @Test
+    void completionTimeoutAggregatorStartsWhenFactoryEnabled() {
+        camelRunner
+                .withBean("cacheManager", CacheManager.class, 
ConcurrentMapCacheManager::new)
+                .withBean(RouteBuilder.class, this::completionTimeoutRoute)
+                
.withPropertyValues("camel.state-store.spring-cache.enabled=true")
+                .run(context -> {
+                    assertThat(context).hasNotFailed();
+                    CamelContext camelContext = 
context.getBean(CamelContext.class);
+                    assertThat(camelContext.getStatus().isStarted()).isTrue();
+                    assertThat(camelContext.getRoute("timeout")).isNotNull();
+                });
+    }
+
+    @Test
+    void cacheEipTtlStillExpiresWhenFactoryEnabled() {
+        camelRunner
+                .withBean("cacheManager", CacheManager.class, 
ConcurrentMapCacheManager::new)
+                .withBean(RouteBuilder.class, this::cacheEipRoute)
+                
.withPropertyValues("camel.state-store.spring-cache.enabled=true")
+                .run(context -> {
+                    
assertThat(context).doesNotHaveBean(KeyValueRepository.class);
+                    CamelContext camelContext = 
context.getBean(CamelContext.class);
+                    ProducerTemplate template = 
camelContext.createProducerTemplate();
+                    try {
+                        assertThat(callCache(template, 
1)).isEqualTo("computed-1");
+                        assertThat(callCache(template, 
2)).isEqualTo("computed-1");
+                        await().atMost(5, TimeUnit.SECONDS)
+                                .pollDelay(Duration.ofMillis(250))
+                                .untilAsserted(() -> 
assertThat(callCache(template, 3)).isEqualTo("computed-3"));
+                    } finally {
+                        template.stop();
+                    }
+                });
+    }
+
+    private RouteBuilder optimisticLockingRoute() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:agg").routeId("agg")
+                        .aggregate(header("id"), new 
UseLatestAggregationStrategy())
+                        .completionSize(2).optimisticLocking()
+                        .to("mock:agg");
+            }
+        };
+    }
+
+    private RouteBuilder completionTimeoutRoute() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:timeout").routeId("timeout")
+                        .aggregate(header("id"), new 
UseLatestAggregationStrategy())
+                        .completionTimeout(1000)
+                        .to("mock:timeout");
+            }
+        };
+    }
+
+    private RouteBuilder cacheEipRoute() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:cached")
+                        .cache(header("id"))
+                            .ttl(200)
+                            .setBody(simple("computed-${header.n}"))
+                        .end();
+            }
+        };
+    }
+
+    private static Object callCache(ProducerTemplate template, int n) {
+        return template.requestBodyAndHeaders("direct:cached", null, 
Map.of("id", "k", "n", n));
+    }
+}
diff --git 
a/components-starter/camel-state-store-starter/src/test/java/org/apache/camel/component/statestore/springboot/cache/SpringCacheStateStoreRedisIT.java
 
b/components-starter/camel-state-store-starter/src/test/java/org/apache/camel/component/statestore/springboot/cache/SpringCacheStateStoreRedisIT.java
new file mode 100644
index 00000000000..c5c6978f0d3
--- /dev/null
+++ 
b/components-starter/camel-state-store-starter/src/test/java/org/apache/camel/component/statestore/springboot/cache/SpringCacheStateStoreRedisIT.java
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.statestore.springboot.cache;
+
+import java.time.Duration;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.statestore.StateStoreBackendFactory;
+import org.apache.camel.component.statestore.StateStoreConstants;
+import 
org.apache.camel.component.statestore.springboot.StateStoreComponentAutoConfiguration;
+import 
org.apache.camel.component.statestore.springboot.StateStoreComponentConverter;
+import org.apache.camel.spi.KeyValueRepository;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.support.DefaultExchange;
+import org.apache.camel.support.DefaultExchangeHolder;
+import org.apache.camel.support.KeyValueAggregationRepository;
+import org.apache.camel.support.KeyValueIdempotentRepository;
+import org.apache.camel.test.infra.redis.services.RedisService;
+import org.apache.camel.test.infra.redis.services.RedisServiceFactory;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.cache.autoconfigure.CacheAutoConfiguration;
+import 
org.springframework.boot.data.redis.autoconfigure.DataRedisAutoConfiguration;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.ProxyCachingConfiguration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.awaitility.Awaitility.await;
+
+@DisabledIfSystemProperty(named = "ci.env.name", matches = "github.com",
+        disabledReason = "Disabled on GH Action due to Docker limit")
+class SpringCacheStateStoreRedisIT {
+
+    @RegisterExtension
+    static RedisService redis = RedisServiceFactory.createService();
+
+    private ApplicationContextRunner runner() {
+        return new ApplicationContextRunner()
+                .withConfiguration(AutoConfigurations.of(
+                        CamelAutoConfiguration.class,
+                        DataRedisAutoConfiguration.class,
+                        CacheAutoConfiguration.class,
+                        StateStoreComponentAutoConfiguration.class,
+                        SpringCacheStateStoreAutoConfiguration.class))
+                .withUserConfiguration(ProxyCachingConfiguration.class, 
StateStoreComponentConverter.class)
+                .withPropertyValues(
+                        "spring.main.banner-mode=off",
+                        "camel.state-store.spring-cache.enabled=true",
+                        "spring.cache.type=redis",
+                        
"spring.cache.cache-names=orders,users,idempotent,aggregate",
+                        "spring.data.redis.host=" + redis.host(),
+                        "spring.data.redis.port=" + redis.port());
+    }
+
+    @Test
+    void stateStoreOperationsUseRedisCacheManager() {
+        runner().run(context -> {
+            assertThat(context).hasNotFailed();
+            
assertThat(context.getBean(CacheManager.class)).isInstanceOf(RedisCacheManager.class);
+            assertThat(context).hasSingleBean(StateStoreBackendFactory.class);
+            assertThat(context).doesNotHaveBean(KeyValueRepository.class);
+
+            CamelContext camelContext = context.getBean(CamelContext.class);
+            ProducerTemplate template = camelContext.createProducerTemplate();
+            try {
+                Object previous = 
template.requestBodyAndHeader("state-store:orders?operation=put", "order-1",
+                        StateStoreConstants.KEY, "1");
+                assertThat(previous).isNull();
+                
assertThat(template.requestBodyAndHeader("state-store:orders?operation=get", 
null,
+                        StateStoreConstants.KEY, "1")).isEqualTo("order-1");
+                
assertThat(template.requestBodyAndHeader("state-store:orders?operation=contains",
 null,
+                        StateStoreConstants.KEY, "1")).isEqualTo(true);
+
+                Object existing = 
template.requestBodyAndHeader("state-store:orders?operation=putIfAbsent", 
"order-2",
+                        StateStoreConstants.KEY, "1");
+                assertThat(existing).isEqualTo("order-1");
+                
assertThat(template.requestBodyAndHeader("state-store:orders?operation=get", 
null,
+                        StateStoreConstants.KEY, "1")).isEqualTo("order-1");
+
+                Object deleted = 
template.requestBodyAndHeader("state-store:orders?operation=delete", null,
+                        StateStoreConstants.KEY, "1");
+                assertThat(deleted).isEqualTo("order-1");
+                
assertThat(template.requestBodyAndHeader("state-store:orders?operation=contains",
 null,
+                        StateStoreConstants.KEY, "1")).isEqualTo(false);
+
+                
template.requestBodyAndHeader("state-store:users?operation=put", "user-1",
+                        StateStoreConstants.KEY, "1");
+                
assertThat(template.requestBodyAndHeader("state-store:users?operation=get", 
null,
+                        StateStoreConstants.KEY, "1")).isEqualTo("user-1");
+            } finally {
+                template.stop();
+            }
+        });
+    }
+
+    @Test
+    void keysAndSizeThrowUnsupportedOperationException() {
+        runner().run(context -> {
+            StateStoreBackendFactory factory = 
context.getBean(StateStoreBackendFactory.class);
+            KeyValueRepository repository = factory.createBackend("orders");
+            repository.put("k", "v");
+
+            
assertThatThrownBy(repository::keys).isInstanceOf(UnsupportedOperationException.class);
+            
assertThatThrownBy(repository::size).isInstanceOf(UnsupportedOperationException.class);
+            assertThat(repository.get("k")).isEqualTo("v");
+        });
+    }
+
+    @Test
+    void explicitEipAdaptersRoundTripSerializableValues() {
+        runner().run(context -> {
+            CacheManager cacheManager = context.getBean(CacheManager.class);
+            CamelContext camelContext = context.getBean(CamelContext.class);
+
+            KeyValueIdempotentRepository idempotent
+                    = new KeyValueIdempotentRepository(new 
SpringCacheKeyValueRepository(cacheManager, "idempotent"));
+            idempotent.start();
+            try {
+                assertThat(idempotent.add("msg-1")).isTrue();
+                assertThat(idempotent.add("msg-1")).isFalse();
+                assertThat(idempotent.contains("msg-1")).isTrue();
+            } finally {
+                idempotent.stop();
+            }
+
+            SpringCacheKeyValueRepository aggregateStore
+                    = new SpringCacheKeyValueRepository(cacheManager, 
"aggregate");
+            KeyValueAggregationRepository aggregationRepository = new 
KeyValueAggregationRepository(aggregateStore);
+            aggregationRepository.setCamelContext(camelContext);
+            aggregationRepository.start();
+            try {
+                Exchange exchange = new DefaultExchange(camelContext);
+                exchange.getMessage().setBody("payload");
+                aggregationRepository.add(camelContext, "corr-1", exchange);
+
+                assertThat(aggregateStore.get("aggregate:corr-1"))
+                        .isInstanceOf(DefaultExchangeHolder.class);
+
+                Exchange restored = aggregationRepository.get(camelContext, 
"corr-1");
+                assertThat(restored).isNotNull();
+                
assertThat(restored.getMessage().getBody()).isEqualTo("payload");
+            } finally {
+                aggregationRepository.stop();
+            }
+        });
+    }
+
+    @Test
+    void providerLevelTimeToLiveExpiresEntries() {
+        runner()
+                .withPropertyValues("spring.cache.redis.time-to-live=2s")
+                .run(context -> {
+                    StateStoreBackendFactory factory = 
context.getBean(StateStoreBackendFactory.class);
+                    KeyValueRepository repository = 
factory.createBackend("orders");
+                    repository.put("expiring", "value");
+                    assertThat(repository.get("expiring")).isEqualTo("value");
+
+                    await().atMost(5, TimeUnit.SECONDS)
+                            .pollInterval(Duration.ofMillis(50))
+                            .untilAsserted(() -> 
assertThat(repository.get("expiring")).isNull());
+                });
+    }
+}
diff --git a/core/camel-spring-boot/src/main/docs/spring-boot.adoc 
b/core/camel-spring-boot/src/main/docs/spring-boot.adoc
index b52750d95f3..3a83148fca1 100644
--- a/core/camel-spring-boot/src/main/docs/spring-boot.adoc
+++ b/core/camel-spring-boot/src/main/docs/spring-boot.adoc
@@ -755,4 +755,4 @@ If you encounter issues with virtual threads:
 1. **Check JDK Version**: Ensure you're running JDK 21 or later
 2. **Verify Property Setting**: Confirm `spring.threads.virtual.enabled=true` 
is set
 3. **Review Logs**: Check for virtual thread configuration messages in startup 
logs
-4. **Monitor Thread Usage**: Use JVM monitoring tools to observe virtual 
thread behavior
\ No newline at end of file
+4. **Monitor Thread Usage**: Use JVM monitoring tools to observe virtual 
thread behavior
diff --git a/docs/spring-boot/modules/ROOT/pages/starters/state-store.adoc 
b/docs/spring-boot/modules/ROOT/pages/starters/state-store.adoc
index 53ddafa63ec..a9eeaba5253 100644
--- a/docs/spring-boot/modules/ROOT/pages/starters/state-store.adoc
+++ b/docs/spring-boot/modules/ROOT/pages/starters/state-store.adoc
@@ -21,9 +21,69 @@ Please refer to the above links for usage and configuration 
details.
 </dependency>
 ----
 
+== Usage
+
+=== Choosing a backend
+
+The State Store component supports Spring Cache and Camel `KeyValueRepository` 
backends.
+
+==== Spring Cache
+
+Set `camel.state-store.spring-cache.enabled=true` to register a 
`StateStoreBackendFactory` backed by Spring's `CacheManager`. Each state-store 
name maps to a Spring cache with the same name, reusing the application's 
`spring.cache.*` configuration.
+
+The factory is registered when a single `CacheManager` candidate is available 
and no other `StateStoreBackendFactory` bean is defined. It does not register a 
global `KeyValueRepository` bean.
+
+==== Camel KeyValueRepository
+
+Alternatively, use a Camel `KeyValueRepository` implementation, such as 
`camel-redis`, `camel-caffeine`, `camel-jcache`, `camel-sql`, or 
`camel-infinispan`. Define the repository as a bean and leave 
`camel.state-store.spring-cache.enabled` disabled. The State Store component 
automatically discovers the repository.
+
+These repositories can also be discovered by Camel features that support 
`KeyValueRepository`, including the Aggregate EIP, Idempotent Consumer, and 
Cache EIP.
+
+==== Configuration examples
+
+To use Spring Cache, configure a cache provider and enable the factory:
+
+[source,properties]
+----
+spring.cache.type=caffeine
+spring.cache.cache-names=orders,users
+camel.state-store.spring-cache.enabled=true
+----
+
+Spring Boot creates the `CacheManager` from `spring.cache.*` only when the 
application enables caching with `@EnableCaching`; otherwise, provide your own 
`CacheManager` bean. Without a single eligible `CacheManager`, the factory is 
not registered, and stores may fall back to the default in-memory repository. 
If `spring.cache.cache-names` specifies a fixed set of names, include every 
state-store name you use. A dynamic cache manager can create caches on demand.
+
+To use a specific Camel repository, register it as a bean, for example under 
the name `redisRepo`, and select it on the endpoint:
+
+[source,java]
+----
+from("direct:order")
+    .setHeader("CamelStateStoreKey", simple("${header.orderId}"))
+    .to("state-store:orders?backend=#redisRepo");
+----
+
+==== Using both backends
+
+When the Spring Cache factory is enabled, it is the default backend for 
state-store endpoints unless an endpoint explicitly selects another backend or 
a component-level backend factory takes precedence.
+
+You can therefore use Spring Cache for ordinary stores and explicitly select a 
Camel repository for stores that need its additional capabilities.
+
+== Limitations
+
+=== Spring Cache
+
+Spring Cache provides a common API, but some operations depend on the 
underlying cache provider.
+
+* **Per-entry TTL:** Spring Cache has no portable per-entry TTL API. A 
positive, non-zero TTL requested through the repository is not applied by the 
Spring adapter. Configure expiration using the underlying cache provider, for 
example with `spring.cache.redis.time-to-live` or a Caffeine specification.
+* **Atomic operations:** Spring Cache does not provide a portable atomic 
get-and-put operation. The adapter's `put` and `delete` read the previous value 
and then write or evict separately, so the returned previous value is not 
atomic. `putIfAbsent` delegates to the provider's Spring Cache implementation; 
its atomicity depends on that provider. Conditional `replace` and conditional 
`delete` may use non-atomic check-then-act operations.
+* **Key enumeration and size:** `keys()` and `size()` are supported only when 
`Cache.getNativeCache()` returns a `ConcurrentMap`, such as with the simple 
cache provider. They operate on a snapshot of current string keys. Other 
providers, including Caffeine, Redis, and JCache, do not support these 
operations through the Spring adapter.
+
+=== Camel KeyValueRepository
+
+Choose a Camel repository when you need capabilities beyond the portable 
Spring Cache API, such as per-entry TTL, atomic `putIfAbsent` or `replace`, 
conditional deletion, and key enumeration or size. Actual support and 
guarantees depend on the selected repository implementation.
+
 == Spring Boot Auto-Configuration
 
-The starter supports 4 options, which are listed below.
+The starter supports 5 options, which are listed below.
 
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
@@ -32,4 +92,5 @@ The starter supports 4 options, which are listed below.
 | camel.component.state-store.backend-factory | Factory that creates a 
dedicated backend for each store name. When set, it takes precedence over 
registry auto-discovery for endpoints without an explicit backend. The option 
is a org.apache.camel.component.statestore.StateStoreBackendFactory type. |  | 
StateStoreBackendFactory
 | camel.component.state-store.enabled | Whether to enable auto configuration 
of the state-store component. This is enabled by default. |  | Boolean
 | camel.component.state-store.lazy-start-producer | Whether the producer 
should be started lazy (on the first message). By starting lazy you can use 
this to allow CamelContext and routes to startup in situations where a producer 
may otherwise fail during starting and cause the route to fail being started. 
By deferring this startup to be lazy then the startup failure can be handled 
during routing messages via Camel's routing error handlers. Beware that when 
the first message is processed  [...]
+| camel.state-store.spring-cache.enabled | Whether to register a 
StateStoreBackendFactory that creates a Spring Cache-backed KeyValueRepository 
for each state-store name. Disabled by default. Requires a single CacheManager 
bean and no user-defined StateStoreBackendFactory. Does not register a global 
KeyValueRepository. | false | Boolean
 |===

Reply via email to