Skip to content
Development
Skill

/spring-boot-event-driven-patterns

Provides Event-Driven Architecture (EDA) patterns for Spring Boot — creates domain events, configures ApplicationEvent and @TransactionalEventListener, sets up Kafka producers and consumers, and implements the transactional outbox pattern for reliable distributed messaging. Use

From plugin
developer-kit
371116 skills44 agents35 commands2 MCP

Claude Code

$ npx -y skills add giuseppe-trisciuoglio/developer-kit --skill spring-boot-event-driven-patterns --agent claude-code

SKILL.md

spring-boot-event-driven-patterns.SKILL.md
name: spring-boot-event-driven-patterns
description: Provides Event-Driven Architecture (EDA) patterns for Spring Boot — creates domain events, configures ApplicationEvent and @TransactionalEventListener, sets up Kafka producers and consumers, and implements the transactional outbox pattern for reliable distributed messaging. Use when implementing event-driven systems in Spring Boot, setting up async messaging with Kafka, publishing domain events from DDD aggregates, or needing reliable event publishing with the outbox pattern.
allowed-tools: Read, Write, Edit, Bash

Spring Boot Event-Driven Patterns

Overview

Implement Event-Driven Architecture (EDA) patterns in Spring Boot 3.x using domain events, ApplicationEventPublisher, `@TransactionalEventListener`, and distributed messaging with Kafka and Spring Cloud Stream.

When to Use

  • Implementing event-driven microservices with Kafka messaging
  • Publishing domain events from aggregate roots in DDD architectures
  • Setting up transactional event listeners that fire after database commits
  • Adding async messaging with producers and consumers via Spring Kafka
  • Ensuring reliable event delivery using the transactional outbox pattern
  • Replacing synchronous calls with event-based communication between services

Quick Reference

| Concept | Description | |---------|-------------| | **Domain Events** | Immutable events extending `DomainEvent` base class with eventId, occurredAt, correlationId | | **Event Publishing** | `ApplicationEventPublisher.publishEvent()` for local, `KafkaTemplate` for distributed | | **Event Listening** | `@TransactionalEventListener(phase = AFTER_COMMIT)` for reliable handling | | **Kafka** | `@KafkaListener(topics = "...")` for distributed event consumption | | **Spring Cloud Stream** | Functional programming model with `Consumer` beans | | **Outbox Pattern** | Atomic event storage with business data, scheduled publisher |

Examples

Monolithic to Event-Driven Refactoring

**Before (Anti-Pattern):**

@Transactional
public Order processOrder(OrderRequest request) {
    Order order = orderRepository.save(request);
    inventoryService.reserve(order.getItems()); // Blocking
    paymentService.charge(order.getPayment()); // Blocking
    emailService.sendConfirmation(order); // Blocking
    return order;
}

**After (Event-Driven):**

@Transactional
public Order processOrder(OrderRequest request) {
    Order order = Order.create(request);
    orderRepository.save(order);

    // Publish event after transaction commits
    eventPublisher.publishEvent(new OrderCreatedEvent(order.getId(), order.getItems()));

    return order;
}

@Component
public class OrderEventHandler {
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void handleOrderCreated(OrderCreatedEvent event) {
        // Execute asynchronously after the order is saved
        inventoryService.reserve(event.getItems());
        paymentService.charge(event.getPayment());
    }
}

See [examples.md](references/examples.md) for complete working examples.

Instructions

1. Design Domain Events

Create immutable event classes extending a base `DomainEvent` class:

public abstract class DomainEvent {
    private final UUID eventId;
    private final LocalDateTime occurredAt;
    private final UUID correlationId;
}

public class ProductCreatedEvent extends DomainEvent {
    private final ProductId productId;
    private final String name;
    private final BigDecimal price;
}

See [domain-events-design.md](references/domain-events-design.md) for patterns.

2. Publish Events from Aggregates

Add domain events to aggregate roots, publish via `ApplicationEventPublisher`:

@Service
@Transactional
public class ProductService {
    public Product createProduct(CreateProductRequest request) {
        Product product = Product.create(request.getName(), request.getPrice(), request.getStock());
        repository.save(product);

        product.getDomainEvents().forEach(eventPublisher::publishEvent);
        product.clearDomainEvents();

        return product;
    }
}

See [aggregate-root-patterns.md](references/aggregate-root-patterns.md) for DDD patterns.

3. Handle Events Transactionally

Use `@TransactionalEventListener` for reliable event handling:

@Component
public class ProductEventHandler {
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void onProductCreated(ProductCreatedEvent event) {
        notificationService.sendProductCreatedNotification(event.getName());
    }
}

**Validate:** Confirm the event handler fires only after the transaction commits by checking that the database state is committed before the handler executes.

See [event-handling.md](references/event-handling.md) for handling patterns.

4. Configure Kafka Infrastructure

Configure KafkaTemplate for publishing, `@KafkaListener` for consuming:

spring:
  kafka:
    bootstrap-servers: localhost:9092
    producer:
      value-serializer: org.springframework.kafka.support.serializer.JsonSerializer

**Validate:** Send a test event via `KafkaTemplate` and confirm it appears in the consumer logs before proceeding to production patterns.

See [dependency-setup.md](references/dependency-setup.md) and [configuration.md](references/configuration.md).

5. Implement Outbox Pattern

Create `OutboxEvent` entity for atomic event storage:

@Entity
public class OutboxEvent {
    private UUID id;
    private String aggregateId;
    private String eventType;
    private String payload;
    private LocalDateTime publishedAt;
}

**Validate:** Confirm the scheduled processor picks up pending events by checking the `publishedAt` timestamp is set after the scheduled run.

Scheduled processor publishes pending events. See [outbox-pattern.md](references/outbox-pattern.md).

6. Handle Failure Scenarios

Implement retry logic, dead-letter

Read more
@giuseppe-trisciuoglio
Ships withdeveloper-kit

Modular plugin marketplace for Claude Code and agentic CLIs, with validated, spec-driven skills, agents, commands, and workflows for Java, TypeScript, Python, PHP, AWS, and AI.

371116 skills44 agents2 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
371
Star history of giuseppe-trisciuoglio/developer-kit on GitHub, a chart by star-history.com

Other skills on developer-kit.

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills2w309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react5d252k
@facebook@facebookInstall Skill

Questions about spring-boot-event-driven-patterns.

Which coding agents can use spring-boot-event-driven-patterns?
spring-boot-event-driven-patterns installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.