From fef4f2e325946edcf256617a7e5a857f609e49dc Mon Sep 17 00:00:00 2001 From: Andres Contreras Date: Wed, 11 Feb 2026 09:41:49 +0100 Subject: [PATCH] docs: add professional README with unified template (#5) Standardize README.md with a consistent template including CI badge, features, installation, quick start, configuration, and documentation sections. Add paths-ignore to ci.yml to skip CI for docs-only changes. --- .github/workflows/ci.yml | 19 +- README.md | 824 +++------------------------------------ 2 files changed, 71 insertions(+), 772 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b9093b6..9567aee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,8 +2,22 @@ name: CI on: push: branches: [develop] + paths-ignore: + - '**.md' + - 'docs/**' + - 'tutorials/**' + - 'examples/**/README.md' + - 'LICENSE' + - '.gitignore' pull_request: branches: [develop, main] + paths-ignore: + - '**.md' + - 'docs/**' + - 'tutorials/**' + - 'examples/**/README.md' + - 'LICENSE' + - '.gitignore' workflow_dispatch: inputs: triggered-by: @@ -13,10 +27,5 @@ on: jobs: build: uses: fireflyframework/.github/.github/workflows/java-ci.yml@main - permissions: - packages: read - contents: read - actions: write with: java-version: '25' - secrets: inherit diff --git a/README.md b/README.md index 0e19e9d..baa6b8d 100644 --- a/README.md +++ b/README.md @@ -1,811 +1,101 @@ -# fireflyframework-domain +# Firefly Framework - Domain [![CI](https://github.com/fireflyframework/fireflyframework-domain/actions/workflows/ci.yml/badge.svg)](https://github.com/fireflyframework/fireflyframework-domain/actions/workflows/ci.yml) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) +[![Java](https://img.shields.io/badge/Java-21%2B-orange.svg)](https://openjdk.org) +[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.x-green.svg)](https://spring.io/projects/spring-boot) -**A comprehensive Spring Boot library for domain-driven design (DDD) with CQRS and SAGA orchestration support.** +> Domain-driven design library enabling DDD patterns with reactive programming, CQRS, and SAGA orchestration support. -## πŸš€ Quick Start +--- -### Maven Dependency +## Table of Contents -```xml - - org.fireflyframework - fireflyframework-domain - 2.0.0-SNAPSHOT - - - - - - org.fireflyframework - fireflyframework-eda - 1.0.0-SNAPSHOT - -``` - -### Auto-Configuration - -The framework auto-configures when detected on the classpath: - -```java -@SpringBootApplication -public class MyApplication { - public static void main(String[] args) { - SpringApplication.run(MyApplication.class, args); - // βœ… CQRS features available via fireflyframework-cqrs - // βœ… SAGA step event bridge configured - // βœ… Distributed tracing is enabled - // βœ… Event publishing available via fireflyframework-eda - } -} -``` - -### Publishing Events with fireflyframework-eda - -For event publishing, use the `fireflyframework-eda` library: - -```java -@Service -public class AccountService { - - private final EventPublisher eventPublisher; - private final AccountRepository accountRepository; - - public Mono createAccount(CreateAccountCommand command) { - return accountRepository.save(buildAccount(command)) - .flatMap(this::publishAccountCreatedEvent); - } - - private Mono publishAccountCreatedEvent(Account account) { - AccountCreatedEvent event = new AccountCreatedEvent( - account.getId(), - account.getCustomerId(), - account.getType(), - account.getBalance() - ); - - Map headers = Map.of( - "event_type", "account.created", - "aggregate_id", account.getId() - ); - - return eventPublisher.publish(event, "account-events", headers) - .thenReturn(account); - } -} -``` - -### Service Client Support - -For service-to-service communication, use the dedicated `fireflyframework-client` library: - -```xml - - org.fireflyframework - fireflyframework-client - 1.0.0-SNAPSHOT - -``` - -See the [fireflyframework-client documentation](../fireflyframework-client/README.md) for comprehensive service client usage. - -## 🎯 Features - -### 🎯 CQRS Framework (via fireflyframework-cqrs) -- **Command & Query Separation**: Clear separation of write and read operations -- **Handler Auto-Discovery**: Automatic registration of command and query handlers -- **Validation**: Jakarta Bean Validation integration -- **Authorization**: Built-in authorization framework -- **Caching**: Intelligent query result caching -- **Metrics & Tracing**: Built-in observability - -### πŸ”„ SAGA Orchestration Integration -- **lib-transactional-engine**: Native integration with saga orchestration -- **Step Event Bridge**: Automatic saga step event publishing via fireflyframework-eda -- **Metadata Enrichment**: Context propagation through saga steps -- **EDA Integration**: Leverages fireflyframework-eda for reliable event delivery - -### πŸ“‘ Event-Driven Architecture (via fireflyframework-eda) -For event publishing and consumption, use the dedicated `fireflyframework-eda` library: -- **Multi-Platform Support**: Kafka, RabbitMQ, AWS SQS/Kinesis, Spring Events -- **Reactive Streams**: Non-blocking event publishing and consumption -- **Resilience Patterns**: Circuit breakers, retries, rate limiting -- **Health Monitoring**: Real-time messaging platform health checks -- **Metrics**: Comprehensive event publishing and consumption metrics - -### 🌍 ExecutionContext (via fireflyframework-cqrs) -- **Context Propagation**: Pass additional data not part of domain objects -- **Multi-Tenancy**: Tenant isolation and context awareness -- **Feature Flags**: Dynamic feature enablement -- **User Context**: Authentication and authorization data -- **Distributed Tracing**: Correlation across service boundaries - -### πŸ” Comprehensive Observability -- **Metrics Collection**: Micrometer integration with custom metrics -- **Health Indicators**: Spring Boot Actuator health checks -- **Distributed Tracing**: Zipkin/Jaeger integration -- **Structured Logging**: JSON logging with correlation context - -## πŸ“– Event-Driven Architecture with fireflyframework-eda - -For event publishing and consumption, this library integrates with `fireflyframework-eda`. See the [fireflyframework-eda documentation](../fireflyframework-eda/README.md) for: - -- **Supported Messaging Platforms**: Kafka, RabbitMQ, AWS SQS, AWS Kinesis, Spring Application Events -- **Configuration Options**: Platform-specific configuration -- **Event Publishing**: Unified EventPublisher API -- **Event Consumption**: Event listeners and handlers -- **Resilience Patterns**: Circuit breakers, retries, rate limiting -- **Health Monitoring**: Platform health indicators - -### Quick Example - -```yaml -# application.yml -firefly: - eda: - enabled: true - default-publisher-type: KAFKA # or RABBIT, SQS, KINESIS, APPLICATION_EVENT - kafka: - bootstrap-servers: localhost:9092 -``` - -```java -@Service -public class OrderService { - - private final EventPublisher eventPublisher; +- [Overview](#overview) +- [Features](#features) +- [Requirements](#requirements) +- [Installation](#installation) +- [Quick Start](#quick-start) +- [Configuration](#configuration) +- [Documentation](#documentation) +- [Contributing](#contributing) +- [License](#license) - public Mono createOrder(CreateOrderCommand command) { - return processOrder(command) - .flatMap(order -> publishOrderCreatedEvent(order)); - } - - private Mono publishOrderCreatedEvent(Order order) { - OrderCreatedEvent event = new OrderCreatedEvent(order.getId(), order.getTotal()); - - Map headers = Map.of( - "event_type", "order.created", - "aggregate_id", order.getId() - ); - - return eventPublisher.publish(event, "order-events", headers) - .thenReturn(order); - } -} -``` - -## πŸ—οΈ Architecture Overview - -### Domain-Driven Design Support - -``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ fireflyframework-domain Architecture β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ CQRS Framework β”‚ β”‚ SAGA Integration β”‚ β”‚ Observability β”‚ β”‚ -β”‚ β”‚ (fireflyframework-cqrs) β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ -β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ -β”‚ β”‚ β”‚ CommandBus β”‚ β”‚ β”‚ β”‚ Step Event β”‚ β”‚ β”‚ β”‚ Metrics β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ QueryBus β”‚ β”‚ β”‚ β”‚ Bridge β”‚ β”‚ β”‚ β”‚ Collection β”‚ β”‚ β”‚ -β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ -β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ -β”‚ β”‚ β”‚ Handler β”‚ β”‚ β”‚ β”‚ Metadata β”‚ β”‚ β”‚ β”‚ Health β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ Auto-Discovery β”‚ β”‚ β”‚ β”‚ Enrichment β”‚ β”‚ β”‚ β”‚ Indicators β”‚ β”‚ β”‚ -β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ -β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ -β”‚ β”‚ β”‚ Validation β”‚ β”‚ β”‚ β”‚ EDA Integration β”‚ β”‚ β”‚ β”‚ Distributed β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ Authorization β”‚ β”‚ β”‚ β”‚ (fireflyframework-eda)β”‚ β”‚ β”‚ β”‚ Tracing β”‚ β”‚ β”‚ -β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ -β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ -β”‚ β”‚ β”‚ ExecutionContextβ”‚ β”‚ β”‚ β”‚ Saga Events β”‚ β”‚ β”‚ β”‚ JSON Logging β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ Multi-Tenancy β”‚ β”‚ β”‚ β”‚ Compensation β”‚ β”‚ β”‚ β”‚ Correlation β”‚ β”‚ β”‚ -β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β”‚ β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ External Dependencies β”‚ β”‚ -β”‚ β”‚ β”‚ β”‚ -β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ -β”‚ β”‚ β”‚ fireflyframework-eda β”‚ β”‚ lib-transactional- β”‚ β”‚ fireflyframework-client β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β”‚ β”‚ engine β”‚ β”‚ β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β”‚ EventPublisher β”‚ β”‚ β”‚ β”‚ StepEventPubl. β”‚ β”‚ β”‚ β”‚ ServiceClient β”‚ β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β”‚ Multi-Platform β”‚ β”‚ β”‚ β”‚ Interface β”‚ β”‚ β”‚ β”‚ REST & gRPC β”‚ β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β”‚ Kafka/RabbitMQ β”‚ β”‚ β”‚ β”‚ Saga β”‚ β”‚ β”‚ β”‚ Circuit Breaker β”‚ β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β”‚ SQS/Kinesis β”‚ β”‚ β”‚ β”‚ Orchestration β”‚ β”‚ β”‚ β”‚ Retry Logic β”‚ β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ -β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β”‚ β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - -## πŸ“‘ Event Publishing with fireflyframework-eda - -For event publishing and consumption, use the dedicated `fireflyframework-eda` library: - -```xml - - org.fireflyframework - fireflyframework-eda - 1.0.0-SNAPSHOT - -``` - -The `fireflyframework-eda` library provides: -- **Multi-Platform Support**: Kafka, RabbitMQ, AWS SQS, AWS Kinesis, Spring Application Events -- **Unified API**: Single EventPublisher interface for all platforms -- **Reactive Streams**: Non-blocking event publishing and consumption -- **Resilience Patterns**: Circuit breakers, retries, rate limiting -- **Health Monitoring**: Real-time messaging platform health checks -- **Metrics**: Comprehensive event publishing and consumption metrics - -### Event Publishing Example - -```java -@Service -public class OrderService { - - private final EventPublisher eventPublisher; - - public Mono processOrder(ProcessOrderCommand command) { - return createOrder(command) - .flatMap(this::validateOrder) - .flatMap(this::publishOrderEvents) - .flatMap(this::updateOrderStatus); - } - - private Mono publishOrderEvents(Order order) { - OrderCreatedEvent event = new OrderCreatedEvent( - order.getId(), - order.getCustomerId(), - order.getTotal() - ); +## Overview - Map headers = Map.of( - "event_type", "order.created", - "aggregate_id", order.getId(), - "source", "order-service" - ); +Firefly Framework Domain provides the foundational building blocks for domain-driven design (DDD) in reactive Spring Boot microservices. It serves as the bridge layer that connects the core framework infrastructure with business domain implementations. - return eventPublisher.publish(event, "order-events", headers) - .thenReturn(order); - } -} -``` - -### Event Consumption Example +The module includes auto-configuration for JSON structured logging and step event bridge configuration for the transactional engine. It enables domain services to participate in SAGA orchestrations and CQRS command/query flows while maintaining clean separation between domain logic and infrastructure concerns. -```java -@Component -public class OrderEventHandler { +This library is typically used in domain-layer microservices that implement business logic following DDD patterns and need integration with the framework's transactional engine and event-driven architecture. - private final NotificationService notificationService; +## Features - @EventListener - public Mono handleOrderCreated(Event event) { - OrderCreatedEvent payload = event.getPayload(); +- Domain-driven design building blocks for reactive microservices +- JSON structured logging auto-configuration +- Step event publisher bridge for transactional engine integration +- Configurable step event properties +- Clean separation between domain and infrastructure layers +- Reactive programming support with Project Reactor - return notificationService.sendOrderConfirmation( - payload.getCustomerId(), - payload.getOrderId(), - payload.getTotal() - ); - } -} -``` +## Requirements -See the [fireflyframework-eda documentation](../fireflyframework-eda/README.md) for complete usage examples, configuration options, and advanced features. +- Java 21+ +- Spring Boot 3.x +- Maven 3.9+ -## πŸ”— Service Client Framework - -For service-to-service communication, use the dedicated `fireflyframework-client` library: +## Installation ```xml org.fireflyframework - fireflyframework-client - 1.0.0-SNAPSHOT - -``` - -The `fireflyframework-client` library provides: -- **Unified API**: Single interface for REST and gRPC communication -- **Circuit Breakers**: Built-in resilience patterns -- **Reactive Programming**: Non-blocking operations with Spring WebFlux -- **Health Checks**: Built-in service health monitoring -- **Request/Response Interceptors**: Extensible request processing -- **Type Safety**: Strong typing with support for generic types - -See the [fireflyframework-client documentation](../fireflyframework-client/README.md) for complete usage examples and configuration options. - - - -## πŸ”„ SAGA Orchestration Integration - -This library provides integration between `lib-transactional-engine` (SAGA orchestration) and `fireflyframework-eda` (event publishing). - -### Dependencies - -```xml - - - org.fireflyframework - lib-transactional-engine - 1.0.0-SNAPSHOT - - - - - org.fireflyframework - fireflyframework-eda - 1.0.0-SNAPSHOT + fireflyframework-domain + 26.01.01 ``` -### Step Event Bridge Configuration - -The `StepEventPublisherBridge` automatically bridges SAGA step events to the EDA infrastructure: - -```yaml -firefly: - stepevents: - enabled: true # Default: true - topic: saga-step-events # Default: step-events - - eda: - enabled: true - default-publisher-type: KAFKA # or RABBIT, SQS, KINESIS, APPLICATION_EVENT - kafka: - bootstrap-servers: localhost:9092 -``` - -### How It Works - -The bridge automatically: -1. Receives step events from `lib-transactional-engine` via the `StepEventPublisher` interface -2. Enriches events with metadata (saga ID, transaction ID, step name, status) -3. Publishes events through `fireflyframework-eda`'s `EventPublisher` to your configured messaging platform - -### SAGA Implementation Example - -For SAGA implementation details, see the [lib-transactional-engine documentation](../lib-transactional-engine/README.md). +## Quick Start ```java @Service -public class MoneyTransferSaga { +public class AccountDomainService { - private final SagaOrchestrator orchestrator; + private final StepEventPublisherBridge stepEvents; - public Mono executeTransfer(TransferCommand command) { - return orchestrator.execute( - SagaDefinition.builder() - .sagaId(command.getSagaId()) - .step("debit-source", () -> debitAccount(command)) - .step("credit-target", () -> creditAccount(command)) - .compensation("debit-source", () -> refundAccount(command)) - .build() - ); - // Step events are automatically published via StepEventPublisherBridge + public AccountDomainService(StepEventPublisherBridge stepEvents) { + this.stepEvents = stepEvents; } -} -``` - -### Step Event Structure - -Step events published through the bridge include: - -```json -{ - "sagaId": "saga-123", - "transactionId": "txn-456", - "stepName": "debit-source-account", - "status": "COMPLETED", - "timestamp": "2025-01-05T10:30:00Z", - "payload": { /* step result data */ } -} -``` - -Headers automatically added: -- `saga_id`: SAGA identifier -- `transaction_id`: Transaction identifier -- `step_name`: Step name -- `step_status`: Step status (STARTED, COMPLETED, FAILED, COMPENSATED) - - -## βš™οΈ Configuration - -### Basic Configuration - -```yaml -# application.yml -firefly: - # CQRS Configuration (from fireflyframework-cqrs) - cqrs: - enabled: true - command: - validation: - enabled: true - query: - cache: - enabled: true - - # SAGA Step Events Configuration - stepevents: - enabled: true # Default: true - topic: saga-step-events # Default: step-events - - # Event-Driven Architecture (from fireflyframework-eda) - eda: - enabled: true - default-publisher-type: KAFKA # KAFKA, RABBIT, SQS, KINESIS, APPLICATION_EVENT - kafka: - bootstrap-servers: localhost:9092 - producer: - acks: all - retries: 3 - consumer: - group-id: ${spring.application.name} - auto-offset-reset: earliest -``` - -### Environment Variables - -All configuration properties can be overridden with environment variables: - -```bash -# CQRS -FIREFLY_CQRS_ENABLED=true -FIREFLY_CQRS_COMMAND_VALIDATION_ENABLED=true -FIREFLY_CQRS_QUERY_CACHE_ENABLED=true - -# SAGA Step Events -FIREFLY_STEPEVENTS_ENABLED=true -FIREFLY_STEPEVENTS_TOPIC=saga-step-events -# Event-Driven Architecture -FIREFLY_EDA_ENABLED=true -FIREFLY_EDA_DEFAULT_PUBLISHER_TYPE=KAFKA -``` - -### Event Publishing Configuration (fireflyframework-eda) - -For detailed event publishing configuration, see the [fireflyframework-eda documentation](../fireflyframework-eda/README.md). - -#### Kafka Configuration -```yaml -firefly: - eda: - default-publisher-type: KAFKA - kafka: - bootstrap-servers: localhost:9092 - producer: - acks: all - retries: 3 - key-serializer: org.apache.kafka.common.serialization.StringSerializer - value-serializer: org.springframework.kafka.support.serializer.JsonSerializer -``` - -#### RabbitMQ Configuration -```yaml -firefly: - eda: - default-publisher-type: RABBIT - rabbit: - host: localhost - port: 5672 - username: guest - password: guest - exchange: domain.events.exchange -``` - -#### AWS Configuration -```yaml -firefly: - eda: - default-publisher-type: SQS - sqs: - region: ${AWS_REGION:us-east-1} - queue-name: domain-events-${spring.profiles.active} -``` - -## πŸ” Observability & Monitoring - -### Spring Boot Actuator Integration - -```yaml -management: - endpoints: - web: - exposure: - include: health,info,metrics,prometheus - endpoint: - health: - show-details: always - show-components: always -``` - -### Available Metrics - -#### CQRS Metrics (from fireflyframework-cqrs) -- `firefly.cqrs.command.executed.total` - Total commands executed -- `firefly.cqrs.command.execution.duration` - Command execution time -- `firefly.cqrs.query.executed.total` - Total queries executed -- `firefly.cqrs.query.execution.duration` - Query execution time -- `firefly.cqrs.query.cache.hits` - Query cache hits -- `firefly.cqrs.query.cache.misses` - Query cache misses - -#### Event Publishing Metrics (from fireflyframework-eda) -- `firefly.eda.events.published.total` - Total events published -- `firefly.eda.events.publishing.duration` - Event publishing time -- `firefly.eda.events.consumed.total` - Total events consumed -- `firefly.eda.events.processing.duration` - Event processing time -- `firefly.eda.events.errors.total` - Event processing errors - -#### SAGA Step Event Metrics -- `firefly.stepevents.published.total` - Total step events published -- `firefly.stepevents.publishing.duration` - Step event publishing time - -### Health Indicators - -The library provides health indicators for SAGA step event bridge: - -```json -{ - "status": "UP", - "components": { - "stepEventBridge": { - "status": "UP", - "details": { - "topic": "saga-step-events", - "publisher": "KAFKA", - "enabled": true - } + public Mono createAccount(CreateAccountRequest request) { + return validateRequest(request) + .flatMap(this::persistAccount) + .flatMap(account -> stepEvents.publish("account-created", account) + .thenReturn(account)); } - } } ``` -For EDA health indicators (Kafka, RabbitMQ, SQS, Kinesis), see the [fireflyframework-eda documentation](../fireflyframework-eda/README.md#observability). - -## πŸ§ͺ Testing - -### Test Configuration +## Configuration ```yaml -# application-test.yml firefly: - cqrs: - enabled: true - command: - validation: - enabled: true - query: - cache: - enabled: false # Disable cache for predictable testing - - stepevents: - enabled: true - topic: test-step-events - - eda: - default-publisher-type: APPLICATION_EVENT # Use in-memory events for testing -``` - -### Integration Testing with Testcontainers - -```java -@SpringBootTest -@Testcontainers -class StepEventBridgeIntegrationTest { - - @Container - static KafkaContainer kafka = new KafkaContainer( - DockerImageName.parse("confluentinc/cp-kafka:latest") - ); - - @Autowired - private StepEventPublisherBridge stepEventBridge; - - @DynamicPropertySource - static void configureProperties(DynamicPropertyRegistry registry) { - registry.add("spring.kafka.bootstrap-servers", kafka::getBootstrapServers); - registry.add("firefly.eda.default-publisher-type", () -> "KAFKA"); - } - - @Test - void shouldPublishStepEvent() { - // Given - StepEventEnvelope stepEvent = StepEventEnvelope.builder() - .sagaId("saga-123") - .transactionId("txn-456") - .stepName("debit-account") - .status("COMPLETED") - .payload(Map.of("accountId", "ACC-123", "amount", 100.00)) - .build(); - - // When - StepVerifier.create(stepEventBridge.publish(stepEvent)) - .verifyComplete(); - } -} -``` - -### Unit Testing - -```java -@ExtendWith(MockitoExtension.class) -class StepEventPublisherBridgeTest { - - @Mock - private EventPublisher eventPublisher; - - private StepEventPublisherBridge bridge; - - @BeforeEach - void setUp() { - bridge = new StepEventPublisherBridge("step-events", eventPublisher); - } - - @Test - void shouldPublishStepEventWithMetadata() { - // Given - when(eventPublisher.publish(any(), anyString(), anyMap())) - .thenReturn(Mono.empty()); - - StepEventEnvelope stepEvent = StepEventEnvelope.builder() - .sagaId("saga-123") - .stepName("test-step") - .build(); - - // When - StepVerifier.create(bridge.publish(stepEvent)) - .verifyComplete(); - - // Then - verify(eventPublisher).publish( - eq(stepEvent), - eq("step-events"), - argThat(headers -> - headers.containsKey("saga_id") && - headers.containsKey("step_name") - ) - ); - } -} -``` - -### Testing with fireflyframework-eda - -For event publishing and consumption testing, see the [fireflyframework-eda testing documentation](../fireflyframework-eda/README.md#testing). - -## πŸ”„ Integration with fireflyframework-cqrs - -For CQRS functionality, use `fireflyframework-cqrs` alongside this library: - -```xml - - - org.fireflyframework - fireflyframework-domain - 2.0.0-SNAPSHOT - - - - - org.fireflyframework - fireflyframework-cqrs - 1.0.0-SNAPSHOT - - - - - org.fireflyframework - fireflyframework-client - 1.0.0-SNAPSHOT - -``` - -**What you get from fireflyframework-cqrs:** -- CommandBus and QueryBus: Central dispatching for commands and queries -- Handler Annotations: @CommandHandlerComponent and @QueryHandlerComponent -- ExecutionContext: Context propagation for tenant isolation and cross-cutting concerns -- Automatic Validation: Jakarta Bean Validation integration -- Query Caching: Intelligent caching with configurable TTL -- Authorization Framework: Integration with fireflyframework-cqrs authorization -- Metrics and Tracing: Built-in observability for CQRS operations - -**Combined Usage Example:** -```java -@Service -public class BankingOrchestrationService { - - private final CommandBus commandBus; // From fireflyframework-cqrs - private final QueryBus queryBus; // From fireflyframework-cqrs - private final DomainEventPublisher eventPublisher; // From fireflyframework-domain - private final ServiceClient paymentService; // From fireflyframework-client - - public Mono processTransfer(TransferRequest request) { - // ExecutionContext is from fireflyframework-cqrs - ExecutionContext context = ExecutionContext.builder() - .userId(request.getUserId()) - .tenantId(request.getTenantId()) - .correlationId(request.getCorrelationId()) - .build(); - - return validateTransfer(request, context) - .flatMap(validation -> executeTransfer(request, context)) - .flatMap(this::publishTransferEvents) - .flatMap(this::notifyExternalSystems); - } - - private Mono executeTransfer(TransferRequest request, ExecutionContext context) { - // Use CQRS command - TransferMoneyCommand command = new TransferMoneyCommand( - request.getSourceAccountId(), - request.getTargetAccountId(), - request.getAmount() - ); - - return commandBus.send(command, context); - } - - private Mono publishTransferEvents(TransferResult result) { - // Use domain events - TransferCompletedEvent event = new TransferCompletedEvent( - result.getTransferId(), - result.getSourceAccountId(), - result.getTargetAccountId(), - result.getAmount() - ); - - return eventPublisher.publish(event) - .thenReturn(result); - } - - private Mono notifyExternalSystems(TransferResult result) { - // Use service client - TransferNotification notification = new TransferNotification( - result.getTransferId(), - result.getAmount(), - "COMPLETED" - ); - - return paymentService.post("/notifications", Void.class) - .withBody(notification) - .execute() - .thenReturn(result); - } -} + domain: + json-logging: + enabled: true + step-events: + enabled: true ``` -> **Note**: For ExecutionContext usage patterns, authorization, caching, and CQRS handler development, see the [fireflyframework-cqrs documentation](../fireflyframework-cqrs/README.md). - -## 🀝 Contributing +## Documentation -1. Follow the existing code style and patterns -2. Write comprehensive tests for new features -3. Update documentation for any API changes -4. Use reactive programming patterns consistently -5. Ensure proper integration with messaging platforms +No additional documentation available for this project. -## πŸ“œ License +## Contributing -Copyright 2024-2026 Firefly Software Solutions Inc +Contributions are welcome. Please read the [CONTRIBUTING.md](CONTRIBUTING.md) guide for details on our code of conduct, development process, and how to submit pull requests. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at +## License - http://www.apache.org/licenses/LICENSE-2.0 +Copyright 2024-2026 Firefly Software Solutions Inc. -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. \ No newline at end of file +Licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) for details.