Skip to content

Getting Started

Cluster Bootstrap Sequence

From cold start to accepting writes in seconds.

Starting Nodes
node-1:5701
FOLLOWER
node-2:5702
FOLLOWER
node-3:5703
FOLLOWER

This guide shows you how to build LoomCache from source, start an embedded node or a three-node Docker cluster, and connect a Java client.

  • Java 25+ for the server (--enable-preview is required for preview APIs such as ScopedValue).
  • Java 17+ for the client SDK.
  • The checked-in Maven wrapper (./mvnw), which verifies the Maven distribution before running.

Check your Java version with the following command:

Terminal window
java --version # expect 25 or higher on the server

Clone the repository and run the full build:

Terminal window
git clone https://github.com/Loom-Cache/loom-cache.git
cd loom-cache
MVN_LOCAL_FORKS="-Dut.forkCount=2 -Dut.threadCount=1 -Dit.forkCount=2 -Dit.threadCount=1"
./mvnw clean verify $MVN_LOCAL_FORKS

The checked-in .mvn/maven.config defaults to 4 Maven forks and 2 test worker threads, so keep the lower override above on resource-constrained workstations. Run one Maven clean/test/verify command per checkout at a time; if you need parallel builds, use separate Git worktrees.

For published tagged releases, applications that connect to an existing cluster depend on loom-client from Maven Central. Before a release is cut, install from the source checkout into your local Maven repository and set loomcache.version to that local project version:

<dependency>
<groupId>com.loomcache</groupId>
<artifactId>loom-client</artifactId>
<version>${loomcache.version}</version>
</dependency>

For Gradle (Kotlin DSL), use the following coordinates:

implementation("com.loomcache:loom-client:$loomcacheVersion")

Spring Boot applications can use the REST and auto-configuration module:

<dependency>
<groupId>com.loomcache</groupId>
<artifactId>loom-spring-boot</artifactId>
<version>${loomcache.version}</version>
</dependency>

The repository contains the following modules:

ModulePurpose
loom-commonShared protocol contracts, configuration, exceptions, and Kryo serialization.
loom-serverTCP server, Raft, data structures, WAL, snapshots, CP subsystem, Chaos harness.
loom-clientClient SDK: smart routing, near cache, pooling, retry.
loom-cliHTTP admin CLI plus local Raft log export tooling.
loom-spring-bootSpring Boot 4.1.0 auto-configuration + REST controllers.
loom-integration-testsMulti-node IT suite, including chaos-tagged cluster suites.

To verify only the server modules, run ./mvnw -pl loom-server,loom-common -am clean test.

The simplest way to try LoomCache is to start an in-process standalone node and use its data structures directly. In standalone() mode the embedded node exposes the server-side structures through getMap, getQueue, getSet, and getTopic. In clustered mode that direct access is rejected; you connect with a LoomClient instead (see Path 2).

The following example starts a standalone node and works with a map:

System.setProperty("loomcache.profile", "development");
EmbeddedLoomCache cache = EmbeddedLoomCache.builder()
.nodeId("embedded-1")
.dataDir("/absolute/path/embedded-data") // dataDir must be an absolute path
.standalone() // required for direct data-structure access
.build();
cache.start();
var map = cache.getMap("users");
map.put("alice", "Alice");
System.out.println(map.get("alice"));
cache.shutdown(); // or cache.close() — EmbeddedLoomCache is AutoCloseable

Builder options include nodeId, clusterName, port (default 5701), host(...), dataDir, allowedDataRoots(...), standalone(), joinCluster(...), enablePersistence(boolean), maxMapEntries, evictionPolicy, maxMemoryBytes, and readBackupData(...). readBackupData(...) enables stale backup reads for standalone/non-production diagnostics only; production profiles reject stale backup reads. enableRest(int) exists, but the embedded REST surface is disabled: any positive port throws.

Start a three-node cluster with Docker Compose:

Terminal window
docker compose up -d
docker compose ps
docker compose port loomcache-node1 7654
docker compose port loomcache-node2 7654
docker compose port loomcache-node3 7654

Compose assigns loopback host ports dynamically so parallel local clusters do not collide. Use docker compose port to discover the host ports:

ServiceCluster → hostSpring REST/Actuator → host
loomcache-node1docker compose port loomcache-node1 7654docker compose port loomcache-node1 8080
loomcache-node2docker compose port loomcache-node2 7654docker compose port loomcache-node2 8080
loomcache-node3docker compose port loomcache-node3 7654docker compose port loomcache-node3 8080

The sample containers expose the binary member port on 7654 and the Spring Boot REST/Actuator port on 8080 (Prometheus metrics are served under /actuator/prometheus). See Deployment (Docker) for production layouts.

To start a Spring Boot smoke cluster from a source checkout, run scripts/start-cluster.sh. It loads the node1, node2, and node3 profiles from config/local-cluster. Those profiles are local-development only and are intentionally not packaged in the Spring Boot jar.

The following example connects a client to the cluster. Replace each placeholder with the host port reported by docker compose port:

LoomClient client = LoomClient.builder()
.addSeed("localhost:<node1-cluster-port>")
.addSeed("localhost:<node2-cluster-port>")
.addSeed("localhost:<node3-cluster-port>")
.requestTimeout(Duration.ofSeconds(15))
.maxRetries(3)
.build();
client.connect();

The following example works with a map, a queue, an atomic long, and a topic:

LoomMap<String, String> users = client.getMap("users");
users.put("alice", "Alice");
LoomQueue<String> tasks = client.getQueue("tasks");
tasks.offer("send-welcome-email");
LoomAtomicLong counter = client.consistencySubsystem().getAtomicLong("hits");
counter.incrementAndGet();
LoomTopic<String> events = client.getTopic("events", String.class);
int sub = events.subscribe(m -> System.out.println("got: " + m));
events.publish("hello");
events.unsubscribe(sub);
client.close();

The following configuration connects a Spring Boot application to the cluster:

loomcache:
cluster:
seeds: [127.0.0.1:5701]
client:
enabled: true
connect-timeout-ms: 5000
request-timeout-ms: 120000

Seeds are binary member endpoints. The standalone defaults reserve 5702 and 5703 for direct admin health listeners, so add them as seeds only if you configured nodes to listen for member traffic on those ports.

The auto-configuration registers a LoomCache client bean (wrapping the underlying LoomClient) when loomcache.client.enabled=true. Setting loomcache.server.enabled=true runs an embedded LoomCache server; in embedded-server mode the client bean is still opt-in with loomcache.client.enabled=true.

LoomCache is an independent open-source project. It is not affiliated with, endorsed by, or sponsored by Hazelcast, Inc. or by any other company whose products are named in this documentation. “Hazelcast” is a trademark of Hazelcast, Inc.; references to it are nominative and describe only migration and comparison. All other product and company names are trademarks of their respective owners and are used for identification purposes only.