Croway commented on code in PR #22158:
URL: https://github.com/apache/camel/pull/22158#discussion_r2989699706


##########
components/camel-state-store/camel-state-store/src/main/docs/state-store-component.adoc:
##########
@@ -0,0 +1,331 @@
+= State Store Component
+:doctitle: State Store
+:shortname: state-store
+:artifactid: camel-state-store
+:description: Perform key-value operations against a pluggable state store 
backend.
+:since: 4.19
+:supportlevel: Preview
+:tabs-sync-option:
+:component-header: Only producer is supported
+
+*Since Camel {since}*
+
+*{component-header}*
+
+The State Store component provides a simple, unified key-value store API with 
pluggable backends.
+It is useful for caching, session state, and scenarios where you need a simple 
object store
+(similar to MuleSoft's Object Store).
+
+By default, an in-memory backend is used (based on `ConcurrentHashMap`), but 
you can plug in
+any custom backend by implementing the `StateStoreBackend` interface or using 
one of the
+provided backend modules:
+
+== When to use State Store vs individual components
+
+Camel also provides dedicated components for 
xref:infinispan-component.adoc[Infinispan],
+xref:spring-redis-component.adoc[Redis], and 
xref:caffeine-cache-component.adoc[Caffeine].
+Use the dedicated component when you need the full feature set of a specific 
technology
+(e.g., Infinispan queries, Redis pub/sub, Caffeine statistics).
+
+Use State Store when:
+
+* You need a *simple key-value API* and want to switch backends without 
changing route logic.
+* You are *migrating from MuleSoft* and want an Object Store equivalent.
+* You want *backend portability* — develop with in-memory, deploy with Redis 
or Infinispan.
+* Your use case is limited to *put, get, delete, contains, keys* operations.
+
+[width="100%",cols="1,2,1",options="header"]
+|===
+| Backend | Module | Description
+| In-Memory | `camel-state-store` | Default. Uses `ConcurrentHashMap` with 
lazy TTL expiry. No external dependencies.
+| Caffeine | `camel-state-store-caffeine` | High-performance local cache with 
proper eviction and per-entry TTL.
+| Redis | `camel-state-store-redis` | Distributed store via Redisson. Supports 
per-entry TTL natively.
+| Infinispan | `camel-state-store-infinispan` | Distributed cache via Hot Rod 
client. Supports per-entry TTL via lifespan.
+|===
+
+== URI Format
+
+----
+state-store:storeName[?options]
+----
+
+Where `storeName` is a logical name for the store. Endpoints with the same 
`storeName`
+share the same backend instance within the same `CamelContext`.
+
+// component-configure options: START
+// component-configure options: END
+
+// component options: START
+include::partial$component-configure-options.adoc[]
+include::partial$component-endpoint-options.adoc[]
+include::partial$component-endpoint-headers.adoc[]
+// component options: END
+
+// endpoint options: START
+// endpoint options: END
+
+== Operations
+
+The operation to perform is set via the URI option `operation` or the header 
`CamelStateStoreOperation`.
+
+[width="100%",cols="1,2,2,2",options="header"]
+|===
+| Operation | Description | Body (input) | Result (body output)
+| `put` | Store a value | The value to store | The previous value (or null)
+| `putIfAbsent` | Store only if key absent | The value to store | The existing 
value (or null if stored)
+| `get` | Retrieve a value | ignored | The stored value (or null)
+| `delete` | Remove a value | ignored | The removed value (or null)
+| `contains` | Check if key exists | ignored | Boolean
+| `keys` | List all keys | ignored | Set<String>
+| `size` | Count entries | ignored | Integer
+| `clear` | Remove all entries | ignored | null
+|===
+
+The key is specified via the header `CamelStateStoreKey` (required for `put`, 
`putIfAbsent`, `get`, `delete`, `contains`).
+
+== TTL (Time-to-Live)
+
+You can set a TTL (in milliseconds) for entries in two ways:
+
+* *Endpoint option*: applies to all `put`/`putIfAbsent` operations on that 
endpoint.
++
+----
+state-store:myStore?operation=put&ttl=60000
+----
+
+* *Per-message header*: the header `CamelStateStoreTtl` (Long) overrides the 
endpoint TTL for that message.
++
+[source,java]
+----
+from("direct:store")
+    .setHeader("CamelStateStoreKey", constant("myKey"))
+    .setHeader("CamelStateStoreTtl", constant(30000L))
+    .to("state-store:myStore?operation=put");
+----
+
+A TTL of `0` (default) means no expiry.
+
+== Examples
+
+=== Java DSL
+
+[tabs]
+====
+Put and Get::
++
+[source,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");
+----
+
+Dynamic operation via header::
++
+[source,java]
+----
+from("direct:dynamic")
+    .setHeader("CamelStateStoreOperation", constant("put"))
+    .setHeader("CamelStateStoreKey", constant("myKey"))
+    .to("state-store:myStore");
+----
+
+Put if absent::
++
+[source,java]
+----
+from("direct:init")
+    .setHeader("CamelStateStoreKey", constant("counter"))
+    .to("state-store:myStore?operation=putIfAbsent");
+----
+====
+
+=== YAML DSL
+
+[source,yaml]
+----
+- route:
+    from:
+      uri: direct:store
+    steps:
+      - setHeader:
+          name: CamelStateStoreKey
+          constant: myKey
+      - to:
+          uri: state-store:myStore?operation=put
+----
+
+== Backends
+
+=== In-Memory (default)
+
+The default backend stores entries in a `ConcurrentHashMap`. TTL expiry is 
lazy -- entries are
+checked and removed on access rather than by a background thread.
+
+No additional dependency is needed beyond `camel-state-store`.
+
+=== Caffeine
+
+Add the dependency:
+
+[source,xml]
+----
+<dependency>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-state-store-caffeine</artifactId>
+</dependency>
+----
+
+Register the backend as a bean and reference it:
+
+[source,java]
+----
+@BindToRegistry("caffeineBackend")
+public CaffeineStateStoreBackend caffeine() {
+    CaffeineStateStoreBackend backend = new CaffeineStateStoreBackend();
+    backend.setMaximumSize(50_000); // default is 10,000
+    return backend;
+}
+----
+
+[source,java]
+----
+from("direct:store")
+    .to("state-store:myStore?operation=put&backend=#caffeineBackend");
+----
+
+Caffeine provides proper eviction policies and active TTL expiration using 
variable expiry.
+
+=== Redis
+
+Add the dependency:
+
+[source,xml]
+----
+<dependency>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-state-store-redis</artifactId>
+</dependency>
+----
+
+Configure and register:
+
+[source,java]
+----
+@BindToRegistry("redisBackend")
+public RedisStateStoreBackend redis() {
+    RedisStateStoreBackend backend = new RedisStateStoreBackend();
+    backend.setRedisUrl("redis://myhost:6379");
+    backend.setMapName("my-app-state"); // Redis map name
+    return backend;
+}
+----
+
+You can also inject a pre-configured `RedissonClient`:
+
+[source,java]
+----
+backend.setRedisson(existingRedissonClient);
+----
+
+Redis provides native per-entry TTL via `RMapCache`. Data is distributed and 
persisted according
+to your Redis configuration.
+
+=== Infinispan
+
+Add the dependency:
+
+[source,xml]
+----
+<dependency>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-state-store-infinispan</artifactId>
+</dependency>
+----
+
+Configure and register:
+
+[source,java]
+----
+@BindToRegistry("infinispanBackend")
+public InfinispanStateStoreBackend infinispan() {

Review Comment:
   @gnodet is this kind of configuration doable only via java beans? would it 
be possible to provide this configuration via properties?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to