Java client library for the Cursus message broker with first-class Spring Boot support.
- Producer — Partition batching, gzip compression, idempotent delivery, configurable linger time
- Consumer — Polling and streaming modes, consumer groups with modulo-based partition assignment
- Consumer Groups — Automatic join/sync/leave lifecycle with heartbeating and rebalance handling
- Spring Boot Starter — Zero-boilerplate auto-configuration and
@CursusListenerannotation - Virtual Threads — Automatically uses
Executors.newVirtualThreadPerTaskExecutor()on Java 21+, falls back to a fixed thread pool on Java 17–20
- Java 17 or later (Java 21+ recommended for Virtual Thread support)
- A running Cursus broker (default port
9000)
Standalone (core library)
// build.gradle
dependencies {
implementation 'io.cursus:cursus-client:0.1.0-SNAPSHOT'
}With Spring Boot
// build.gradle
dependencies {
implementation 'io.cursus:cursus-spring-boot-starter:0.1.0-SNAPSHOT'
implementation 'org.springframework.boot:spring-boot-starter-web'
}import io.cursus.client.config.Acks;
import io.cursus.client.config.CursusProducerConfig;
import io.cursus.client.producer.CursusProducer;
import java.util.List;
CursusProducerConfig config = CursusProducerConfig.builder()
.brokers(List.of("localhost:9000"))
.topic("my-topic")
.partitions(4)
.acks(Acks.ONE)
.batchSize(500)
.lingerMs(100)
.build();
try (CursusProducer producer = new CursusProducer(config)) {
long seq = producer.send("Hello, Cursus!");
producer.flush();
System.out.println("Sent seq=" + seq + ", acked=" + producer.getUniqueAckCount());
}import io.cursus.client.config.ConsumerMode;
import io.cursus.client.config.CursusConsumerConfig;
import io.cursus.client.consumer.CursusConsumer;
import java.util.List;
CursusConsumerConfig config = CursusConsumerConfig.builder()
.brokers(List.of("localhost:9000"))
.topic("my-topic")
.groupId("my-group")
.consumerMode(ConsumerMode.STREAMING)
.build();
CursusConsumer consumer = new CursusConsumer(config);
Runtime.getRuntime().addShutdownHook(new Thread(consumer::close));
consumer.start(msg ->
System.out.printf("offset=%d key=%s payload=%s%n",
msg.getOffset(), msg.getKey(), msg.getPayload()));cursus:
brokers:
- localhost:9000
producer:
topic: my-topic
partitions: 4
acks: one
batch-size: 500
linger-ms: 100
consumer:
topic: my-topic
group-id: my-group
mode: streaming
auto-commit-interval: 5simport io.cursus.client.message.CursusMessage;
import io.cursus.spring.annotation.CursusListener;
import org.springframework.stereotype.Service;
@Service
public class MyEventHandler {
@CursusListener(topic = "my-topic", groupId = "my-group")
public void handle(CursusMessage message) {
System.out.println("Received: " + message.getPayload());
}
}| Document | Description |
|---|---|
| Getting Started | Installation, first message, next steps |
| Architecture | Module structure, data flow, Go SDK mapping |
| Producer Guide | Batching, compression, idempotency, monitoring |
| Consumer Guide | Modes, groups, offsets, shutdown |
| Spring Boot Integration | Auto-configuration, @CursusListener |
| Configuration Reference | All properties with types and defaults |
| Protocol | Wire format, commands, frame structure |
| Virtual Threads | Java 21+ auto-detection and behavior |
| Example | Description |
|---|---|
| standalone/ | 5 standalone Java examples (no Spring) |
| spring-boot/ | Spring Boot REST app with producer and listener |
See each directory's README for run instructions.
Apache License 2.0. See LICENSE.