- 🎯 What is FluxFlow?
- 🚀 Why Choose FluxFlow?
- ✨ Key Features
- 🔥 Quick Example
- 📊 Workflow Visualization
- 💡 Example Use Cases
- ⚡ Quick Start
- 🏗️ Architecture Overview
- 📋 Core Concepts
- 🔗 Resources & Links
- ❓ Frequently Asked Questions
- 🚧 Compatibility
- 🤝 Community & Support
- 👥 Contributors
FluxFlow is a lightweight, developer-friendly workflow engine that transforms how you build and manage business processes. Instead of wrestling with XML configurations or visual designers, you define workflows directly in your Java or Kotlin code – making them testable, maintainable, and type-safe.
Your code IS your workflow.
Transform your Java/Kotlin classes into powerful workflow steps, where properties become state and methods define transitions.
Unlike traditional BPMN engines that scatter logic across multiple artifacts, FluxFlow consolidates everything in your domain code. This means:
- ✅ No XML hell – Pure code-based workflows
- ✅ Type safety – Compile-time verification of your workflows
- ✅ Easy testing – Unit test your business logic naturally
- ✅ Version control friendly – Track changes like any other code
- ✅ IDE support – Full autocomplete, refactoring, and debugging
| Traditional BPMN | FluxFlow |
|---|---|
| 🔴 XML configuration files | 🟢 Pure Java/Kotlin code |
| 🔴 Separated business logic | 🟢 Unified codebase |
| 🔴 Hard to test | 🟢 Easy unit testing |
| 🔴 Designer dependency | 🟢 IDE-native development |
| 🔴 Runtime errors | 🟢 Compile-time safety |
| 🔴 Complex debugging | 🟢 Standard debugging tools |
🏗️ Code-First Architecture
- Step Classes: Your POJOs become workflow steps
- State Management: Properties hold step-specific data
- Action Methods: Methods define transitions and business logic
- Type Safety: Compile-time verification of workflow structure
🔄 Workflow Components
- Workflow Data: Shared information across the entire workflow
- Step Data: Step-specific state that can be queried and updated
- Step Actions: Transitions and business logic execution
- Jobs: Scheduled automatic execution (powered by Quartz)
- Validation: Built-in Jakarta Bean Validation support
🌱 Spring Boot Integration
- Dependency Injection: Full Spring context support
- Auto-Configuration: Zero-configuration setup
- Persistence: Automatic workflow state management
- Testing: Comprehensive test utilities
- Monitoring: Built-in metrics and health checks
🧪 Testing & Quality
- Unit Testing: Test workflow logic like any other code
- Mocking Support: Easy step and action mocking
- Test Utilities: Specialized testing framework
- Coverage: Full code coverage for workflows
Transform this pizza ordering process into executable code:
1. Add FluxFlow to your project:
Gradle (Kotlin DSL)
dependencies {
implementation("de.lise.fluxflow:springboot:0.2.0")
implementation("de.lise.fluxflow:mongo:0.2.0") // For MongoDB persistence
}Gradle (Groovy)
dependencies {
implementation 'de.lise.fluxflow:springboot:0.2.0'
implementation 'de.lise.fluxflow:mongo:0.2.0' // For MongoDB persistence
}Maven
<dependency>
<groupId>de.lise.fluxflow</groupId>
<artifactId>springboot</artifactId>
<version>0.2.0</version>
</dependency>
<dependency>
<groupId>de.lise.fluxflow</groupId>
<artifactId>mongo</artifactId>
<version>0.2.0</version>
</dependency>2. Define your workflow steps:
// 1️⃣ Add Pizza to Cart Step
@Step
class AddPizzaToCartStep(
@Data
@NotEmpty(message = "Cart cannot be empty. Please add at least one pizza before checkout.")
var pizzas: MutableList<Pizza> = mutableListOf()
) {
@Action(beforeExecutionValidation = ValidationBehavior.AllowInvalid)
fun addPizza(pizza: Pizza): AddPizzaToCartStep {
// Add the pizza to cart
pizzas.add(pizza)
// Return to same step for more pizzas
return AddPizzaToCartStep(pizzas)
}
@Action
fun toCheckout(): CheckoutStep {
// Calculate total and proceed to checkout with current pizzas
val total = pizzas.sumOf { it.price }
return CheckoutStep(pizzas, total)
}
}
// 2️⃣ Checkout Step
@Step
class CheckoutStep(
@Data val pizzas: List<Pizza>,
@Data val total: BigDecimal
) {
@Data var deliveryAddress: String = ""
@Data var paymentMethod: String = ""
@Action
fun submitOrder(): Continuation<OrderConfirmation> {
// Process order with pre-calculated total
val confirmation = OrderConfirmation(
orderId = UUID.randomUUID().toString(),
pizzas = pizzas,
total = total,
deliveryAddress = deliveryAddress
)
// Workflow completes successfully
return Continuation.end(confirmation)
}
}
data class Pizza(val name: String, val price: BigDecimal)
data class OrderConfirmation(
val orderId: String,
val pizzas: List<Pizza>,
val total: BigDecimal,
val deliveryAddress: String
)3. Test your workflow logic:
class PizzaOrderWorkflowTest {
@Test
fun `addPizza should add pizza to cart and return to same step`() {
// Arrange
val initialStep = AddPizzaToCartStep()
val pizza = Pizza("Margherita", BigDecimal("12.99"))
// Act
val result = initialStep.addPizza(pizza)
// Assert
assertThat(result.pizzas).hasSize(1)
assertThat(result.pizzas[0]).isEqualTo(pizza)
assertThat(result).isInstanceOf(AddPizzaToCartStep::class.java)
}
@Test
fun `toCheckout should transition to checkout step with current pizzas`() {
// Arrange
val pizzas = mutableListOf(
Pizza("Margherita", BigDecimal("12.99")),
Pizza("Pepperoni", BigDecimal("14.99"))
)
val step = AddPizzaToCartStep(pizzas)
// Act
val result = step.toCheckout()
// Assert
assertThat(result).isInstanceOf(CheckoutStep::class.java)
assertThat(result.pizzas).hasSize(2)
assertThat(result.total).isEqualTo(BigDecimal("27.98"))
}
@Test
fun `submitOrder should create confirmation with pre-calculated total`() {
// Arrange
val pizzas = listOf(
Pizza("Margherita", BigDecimal("12.99")),
Pizza("Pepperoni", BigDecimal("14.99"))
)
val checkoutStep = CheckoutStep(pizzas, BigDecimal("27.98")).apply {
deliveryAddress = "123 Main St"
paymentMethod = "Credit Card"
}
// Act
val result = checkoutStep.submitOrder()
// Assert
assertThat(result.isCompleted).isTrue()
val confirmation = result.completionData as OrderConfirmation
assertThat(confirmation.pizzas).isEqualTo(pizzas)
assertThat(confirmation.total).isEqualTo(BigDecimal("27.98"))
assertThat(confirmation.deliveryAddress).isEqualTo("123 Main St")
assertThat(confirmation.orderId).isNotBlank()
}
}That's it! You now have a fully functional pizza ordering workflow with:
- ✅ Type-safe state management
- ✅ Decision logic with looping
- ✅ Built-in validation rules
- ✅ Comprehensive unit tests
- ✅ Automatic persistence (with Spring Boot)
FluxFlow is well-suited for various business scenarios:
|
🏢 Enterprise Applications
💰 Financial Processing
|
🛒 E-Commerce Applications
🏥 Healthcare Systems
|
Gradle (Kotlin DSL)
dependencies {
implementation("de.lise.fluxflow:springboot:0.2.0")
implementation("de.lise.fluxflow:mongo:0.2.0") // For MongoDB persistence
}Gradle (Groovy)
dependencies {
implementation 'de.lise.fluxflow:springboot:0.2.0'
implementation 'de.lise.fluxflow:mongo:0.2.0' // For MongoDB persistence
}Maven
<dependency>
<groupId>de.lise.fluxflow</groupId>
<artifactId>springboot</artifactId>
<version>0.2.0</version>
</dependency>
<dependency>
<groupId>de.lise.fluxflow</groupId>
<artifactId>mongo</artifactId>
<version>0.2.0</version>
</dependency>// Java Example - Pizza Ordering Step
@Step
public class AddPizzaToCartStep {
@Data
@NotEmpty(message = "Cart cannot be empty. Please add at least one pizza before checkout.")
private List<Pizza> pizzas = new ArrayList<>();
@Action(beforeExecutionValidation = ValidationBehavior.AllowInvalid)
public AddPizzaToCartStep addPizza(Pizza pizza) {
// Add pizza to cart
pizzas.add(pizza);
return new AddPizzaToCartStep(pizzas);
}
@Action
public CheckoutStep toCheckout() {
// Calculate total and proceed to checkout
BigDecimal total = pizzas.stream()
.map(Pizza::getPrice)
.reduce(BigDecimal.ZERO, BigDecimal::add);
return new CheckoutStep(pizzas, total);
}
}@SpringBootApplication
@EnableFluxFlow
class MyApplication
fun main(args: Array<String>) {
runApplication<MyApplication>(*args)
}@RestController
class PizzaOrderController(
private val workflowEngine: WorkflowEngine
) {
@PostMapping("/pizza-orders")
fun startPizzaOrder(): String {
val workflow = workflowEngine.start(AddPizzaToCartStep())
return workflow.id
}
}FluxFlow follows a simple, layered architecture:
- 🔧 Your Application Code: Define workflow steps as regular Java/Kotlin classes
- ⚙️ FluxFlow Engine: Manages workflow execution, state transitions, and persistence
- 💾 Persistence Layer: Stores workflow state (MongoDB, in-memory, or custom implementations)
- 📅 Scheduling: Optional Quartz integration for time-based workflow actions
- 🌱 Spring Integration: Auto-configuration and dependency injection support
| Concept | Description | Example |
|---|---|---|
| 🔄 Workflow | A complete business process | Pizza ordering process |
| 📦 Step | Individual stage in workflow | "Add Pizza to Cart" step |
| 💾 Step Data | State specific to a step | Pizza list, customer ID |
| ⚡ Action | Transition between steps | addPizza() method |
| 🗄️ Workflow Data | Shared data across all steps | Customer info, order ID |
| ⏰ Jobs | Scheduled automatic actions | Send reminder after 30min |
| Resource | Link |
|---|---|
| 📖 Documentation | docs.fluxflow.cloud |
| 🚀 Getting Started | Quick Start Guide |
| 📦 Maven Central | Browse Packages |
| 📝 Changelog | Release Notes |
| 🤝 Contributing | Contribution Guide |
| 🔒 Security | Security Policy |
How does FluxFlow compare to traditional BPMN engines?
FluxFlow takes a code-first approach rather than model-first. Instead of designing workflows in visual tools and then implementing the logic separately, you write your workflows directly in Java/Kotlin. This eliminates the gap between design and implementation, makes testing easier, and leverages your existing development tools.
Can I use FluxFlow without Spring Boot?
Yes! While FluxFlow has excellent Spring Boot integration, the core engine is framework-agnostic. You can use it with other frameworks or in standalone applications by manually configuring the workflow engine components.
What persistence options are available?
FluxFlow supports multiple persistence backends including MongoDB and in-memory storage for testing. The persistence layer is pluggable, so you can implement custom storage backends if needed.
How do I handle long-running workflows?
FluxFlow automatically persists workflow state between steps. Long-running workflows can be paused and resumed, and the engine handles scheduling of future actions through integration with Quartz Scheduler.
Is FluxFlow production-ready?
Yes! FluxFlow is actively used in production environments. It includes comprehensive monitoring, metrics, error handling, and has been battle-tested in enterprise applications.
| Component | Version | Support |
|---|---|---|
| Java | 17+ | ✅ Full Support |
| Kotlin | 2.0+ | ✅ Full Support |
| Spring Boot | 3.0+ | ✅ Full Support |
| Jakarta EE | 9+ | ✅ Full Support |
Found a bug? Report it
Have a question? Start a discussion
Want to contribute? Read our guide
🌟 If FluxFlow helps your project, please consider giving us a star!
We're grateful to these wonderful people who have contributed to FluxFlow:
In Memory:
- Jagadish Singh - We deeply appreciate his valuable contributions to both FluxFlow and our team
Built with ❤️ by Lise GmbH
FluxFlow is open source software licensed under the Apache License 2.0

