plugins/developer-kit-java/skills/spring-boot-event-driven-patterns/SKILL.md
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.
npx skillsauth add giuseppe-trisciuoglio/developer-kit spring-boot-event-driven-patternsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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.
| 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 |
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 for complete working examples.
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 for patterns.
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 for DDD patterns.
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 for handling patterns.
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 and configuration.md.
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.
Implement retry logic, dead-letter queues, idempotent handlers:
@RetryableTopic(attempts = "3")
@KafkaListener(topics = "product-events")
public void handleProductEvent(ProductCreatedEventDto event) {
orderService.onProductCreated(event);
}
Validate: Confirm messages reach the dead-letter topic after exhausting retries before moving to observability.
Enable Spring Cloud Sleuth for distributed tracing, monitor metrics.
ProductCreated (not CreateProduct)@TransactionalEventListener only fire after transaction commitspring-boot-security-jwt — JWT authentication for secure event publishingspring-boot-test-patterns — Testing event-driven applicationsaws-sdk-java-v2-lambda — Event-driven processing with AWS Lambdalangchain4j-tool-function-calling-patterns — AI-driven event processingdevelopment
Provides security review capability for TypeScript/Node.js applications, validates code against XSS, injection, CSRF, JWT/OAuth2 flaws, dependency CVEs, and secrets exposure. Use when performing security audits, before deployment, reviewing authentication/authorization implementations, or ensuring OWASP compliance for Express, NestJS, and Next.js. Triggers on "security review", "check for security issues", "TypeScript security audit".
development
Provides final code cleanup after task review approval. Removes debug logs, temporary comments, dead code, optimizes imports, and improves readability. Use when asked to clean up code, polish, finalize, tidy up, remove technical debt, or prepare code for completion after review. Not for refactoring logic or fixing bugs—focused solely on cosmetic and hygiene cleanup.
tools
Ralph Wiggum-inspired automation loop for specification-driven development. Orchestrates task implementation, review, cleanup, and synchronization using a Python script. Use when: user runs /loop command, user asks to automate task implementation, user wants to iterate through spec tasks step-by-step, or user wants to run development workflow automation with context window management. One step per invocation. State machine: init → choose_task → implementation → review → fix → cleanup → sync → update_done. Supports --from-task and --to-task for task range filtering. State persisted in fix_plan.json.
testing
Creates, updates, validates, and displays the architectural DNA of a project through two shared documents: docs/specs/architecture.md (technology stack, architectural rules, security constraints, AI guardrails) and docs/specs/ontology.md (domain glossary / Ubiquitous Language). Use BEFORE brainstorm as a project setup step, or at any point in the SDD lifecycle to validate specs/tasks against architecture principles. Triggers on 'create constitution', 'update constitution', 'constitution check', 'validate against constitution', 'project principles', 'architectural guardrails', 'setup project architecture', 'define ontology'.