Prerequisites
Java 17+ Spring Boot 3.x requires Java 17 as a minimum.
Spring Boot 3.x Spring MVC or Spring WebFlux — both are supported.
MongoDB Replica Set Change Streams require a Replica Set. A single-node RS is fine for local dev.
MongoDB must be running as a Replica Set — Change Streams are not available on standalone instances. For local development, start MongoDB with --replSet rs0 or use a Docker Compose setup.
Step 1 — Add the dependency
< dependency >
< groupId > io.flowwarden </ groupId >
< artifactId > flowwarden-stream-core </ artifactId >
< version > 1.0.0 </ version >
</ dependency >
No additional dependencies needed. FlowWarden uses only Spring Data MongoDB, which is already on your classpath via spring-boot-starter-data-mongodb.
Add the following to your application.yml:
flowwarden :
default-mode : IMPERATIVE
spring :
data :
mongodb :
uri : mongodb://localhost:27017/mydb?replicaSet=rs0
flowwarden :
default-mode : REACTIVE
spring :
data :
mongodb :
uri : mongodb://localhost:27017/mydb?replicaSet=rs0
flowwarden.default-mode is optional — it defaults to IMPERATIVE when omitted. Only set it explicitly if you need the reactive mode.
Step 3 — Enable FlowWarden
Add @EnableFlowWarden to your main application class:
import io.flowwarden.stream.annotation.EnableFlowWarden;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@ SpringBootApplication
@ EnableFlowWarden
public class MyApplication {
public static void main ( String [] args ) {
SpringApplication . run ( MyApplication . class , args);
}
}
This activates the FlowWarden bean scanner and registers all @ChangeStream classes found during Spring component scanning.
Step 4 — Create your first handler
Declare a Spring bean annotated with @ChangeStream and add a handler method:
Imperative (Spring MVC)
Reactive (Spring WebFlux)
import io.flowwarden.stream.ChangeStreamContext;
import io.flowwarden.stream.annotation.ChangeStream;
import io.flowwarden.stream.annotation.OnChange;
import org.springframework.stereotype.Component;
@ Component
@ ChangeStream ( documentType = Order . class )
public class OrderStream {
@ OnChange
void handleOrderChange ( ChangeStreamContext < Order > ctx ) {
System . out . println ( ctx . summary ());
}
}
Where Order is a Spring Data @Document class:
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@ Document ( collection = "orders" )
public class Order {
@ Id
private String id ;
private String customerEmail ;
private String status ;
// getters, setters...
}
When documentType is set, FlowWarden infers the collection name from the @Document annotation (or the decapitalized class name if none). No need to repeat it in @ChangeStream(collection = "orders").
Step 5 — Run it
Start your application. On boot, you will see a log line for each discovered stream:
INFO i.f.s.i.d.ChangeStreamBeanPostProcessor - Discovered Change Stream 'order-stream' on collection 'orders' (handlers: @OnChange=handleOrderChange, checkpoint: false)
Then insert a document in the orders collection — your handler fires immediately.
db . orders . insertOne ({ customerEmail: "alice@example.com" , status: "PENDING" , total: 49.99 })
What’s next?
How it Works Understand the startup lifecycle and the event processing pipeline
Typed handlers Use @OnInsert, @OnUpdate, @OnDelete for operation-specific logic
Checkpoint & Resume Survive restarts without missing or replaying events
Filtering Events Push aggregation pipelines to MongoDB or filter in Java