Local development
How to run and test Sagaweaw locally — with real saga execution, live dashboard, and zero production credentials required.
Local dev has more moving parts than production. If you just want to ship, see Production → — it's 5 steps with one environment variable.
Prerequisites
- JDK 17+
- Docker (for PostgreSQL)
- Node.js 18+ (only if using the Vite dev server for the dashboard)
1. Start the database
docker run -d \
--name sagaweaw-dev-db \
-e POSTGRES_DB=myapp \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres \
-p 5432:5432 \
postgres:16
Or use your project's existing docker-compose.yml if it already includes a db service.
2. Configure dev properties
# application-dev.properties
spring.datasource.url=jdbc:postgresql://localhost:5432/myapp
spring.datasource.username=postgres
spring.datasource.password=postgres
sagaweaw.observability.token=dev-token
sagaweaw.kafka.enabled=false
sagaweaw.auto-start.enabled=true
Run with the dev profile:
./gradlew bootRun --args='--spring.profiles.active=dev'
# or
./mvnw spring-boot:run -Dspring-boot.run.profiles=dev
3. Open the dashboard
The dashboard is embedded in your application by default:
http://localhost:8080/sagaweaw
Enter the token dev-token and you see the live feed.
4. Fire sagas automatically with @AutoStart + SagaSampler
Add @AutoStart to your saga and implement SagaSampler to provide sample data. The saga fires on every application startup when sagaweaw.auto-start.enabled=true.
@Saga("order-processing")
@AutoStart
@Component
public class OrderSaga
implements SagaDefinition<OrderSaga.Context>,
SagaSampler<OrderSaga.Context> {
@Override
public Context sampleContext() {
return new Context(
UUID.fromString("00000000-0000-0000-0000-000000000001"),
"customer-42",
new BigDecimal("99.90")
);
}
// ... define() with your real steps
}
Kotlin DSL equivalent:
@Saga(name = "order-processing")
@AutoStart
@Component
class OrderSaga(...) : SagaDefinition<OrderSaga.Context>, SagaSampler<OrderSaga.Context> {
override fun sampleContext() = Context(
orderId = UUID.fromString("00000000-0000-0000-0000-000000000001"),
customerId = "customer-42",
amount = BigDecimal("99.90"),
)
}
The sampleContext() you implement also pre-fills the registry endpoint (GET /api/sagas/registry), so any HTTP client (Postman, curl, the trigger endpoint) can see the expected shape of your context without reading the code.
sagaweaw.auto-start.enabled defaults to false. Keep it out of your application.properties and application-prod.properties. Only set it in application-dev.properties or application-local.properties.
5. Trigger sagas manually
Use the built-in trigger endpoint to fire a saga with any context:
# List registered sagas and their context schema
curl -H "X-Sagaweaw-Token: dev-token" \
http://localhost:8080/api/sagas/registry
# Fire a saga by name
curl -X POST \
-H "X-Sagaweaw-Token: dev-token" \
-H "Content-Type: application/json" \
-d '{"orderId":"some-uuid","customerId":"cust-1","amount":99.90}' \
http://localhost:8080/api/sagas/trigger/order-processing
This is useful when your saga steps need real data from the database (existing records, foreign keys) that sampleContext() can't provide.
6. Optional — Vite dev server for dashboard hot reload
If you're working on the dashboard itself or prefer hot reload, run the Vite dev server:
cd sagaweaw-dashboard
npm install
npm run dev # http://localhost:8484, proxies /api → localhost:8080
Add CORS config so the browser can reach the API from port 8484:
sagaweaw.observability.cors.allowed-origins=http://localhost:8484
Switch to standalone mode:
sagaweaw.dashboard.mode=standalone
embedded (default): dashboard served by your Spring Boot app at /sagaweaw. No extra process.
standalone: Vite dev server on port 8484 with hot reload. Requires npm run dev and CORS config.
Troubleshooting
Dashboard returns 404 after adding the dependency
The jar from Maven Central includes the dashboard assets. If you built from source without -Pfrontend-build, the assets are missing. Run:
./mvnw package -Pfrontend-build -pl sagaweaw-spring -am -DskipTests
Or just use the published artifact from Maven Central.
Token returns 403 even though it looks correct
The token comparison is constant-time. Check that there are no leading/trailing spaces in SAGAWEAW_TOKEN. Set it explicitly without shell expansion:
export SAGAWEAW_TOKEN="your-exact-token"
@AutoStart fires but saga fails immediately
The sampleContext() UUIDs probably reference records that don't exist in your dev database. Either:
- Add a Flyway dev migration (
V99__dev_seed.sql) that creates the records your sample context points to - Or use the trigger endpoint with real IDs from your dev database instead of
@AutoStart