spring-boot-event-driven-patterns — скилл для Claude Code: события
Скилл для Spring Boot 3.x: доменные события, @TransactionalEventListener, Kafka и transactional outbox. Пригодится, когда синхронные вызовы между сервисами пора заменить на события.
npx skills add giuseppe-trisciuoglio/developer-kit --skill spring-boot-event-driven-patterns -a claude-codeЧто делает spring-boot-event-driven-patterns
Скилл даёт агенту набор шаблонов для событийной архитектуры в Spring Boot. Он описывает доменные события на базе класса DomainEvent с eventId, occurredAt и correlationId, публикацию через ApplicationEventPublisher и обработку в @TransactionalEventListener с фазой AFTER_COMMIT, чтобы слушатель срабатывал уже после коммита транзакции.
Отдельный блок — распределённый обмен через Kafka: настройка KafkaTemplate и @KafkaListener, конфигурация сериализации в application.yml, а также функциональная модель Spring Cloud Stream с бинами Consumer. Для надёжной доставки есть transactional outbox: сущность OutboxEvent хранит событие в той же транзакции, что и бизнес-данные, а запланированный процессор публикует накопившееся. Плюс retry с @RetryableTopic и dead-letter топики для тех сообщений, что так и не прошли.
Скилл работает с файлами и запускает команды: ему разрешены Read, Write, Edit и Bash. Для Kafka-части понадобится сам брокер — в примерах конфигурации указан localhost:9092. Если у вас брокер не поднят локально, шаблоны продюсера и консьюмера вы просто не сможете проверить, так что сначала подготовьте окружение.
Какие задачи решает
- заменить блокирующие вызовы между сервисами на публикацию событий
- настроить слушатель, который срабатывает после коммита транзакции
- подключить Kafka-продюсер и консьюмер в Spring Boot
- сохранить событие в одной транзакции с бизнес-данными через outbox
- добавить retry и dead-letter топик для упавших сообщений
Примеры запросов агенту
- Перепиши
processOrderтак, чтобы после сохранения заказа публиковалось доменное событие, а резерв товара и оплата шли в обработчике. - Настрой
@KafkaListenerдля топикаproduct-eventsи добавь@RetryableTopicна 3 попытки. - Покажи, как реализовать transactional outbox: сущность
OutboxEventи процессор, который публикует неотправленные события.
Как установить spring-boot-event-driven-patterns
1Через Skills CLI (Vercel)
npx skills add giuseppe-trisciuoglio/developer-kit --skill spring-boot-event-driven-patterns -a claude-code2Вручную: положить файлы
~/.claude/skills/spring-boot-event-driven-patterns/SKILL.mdПапка скилла целиком; для одного проекта — .claude/skills/spring-boot-event-driven-patterns/
1Через Skills CLI (Vercel)
npx skills add giuseppe-trisciuoglio/developer-kit --skill spring-boot-event-driven-patterns -a codex2Вручную: положить файлы
.agents/skills/spring-boot-event-driven-patterns/SKILL.mdДля всех проектов — ~/.agents/skills/
1Через Skills CLI (Vercel)
npx skills add giuseppe-trisciuoglio/developer-kit --skill spring-boot-event-driven-patterns -a cursor2Вручную: положить файлы
.cursor/skills/spring-boot-event-driven-patterns/SKILL.mdCursor читает и .agents/skills/, и .claude/skills/
1GitHub CLI
gh skill install giuseppe-trisciuoglio/developer-kit spring-boot-event-driven-patterns2Вручную: положить файлы
.github/skills/spring-boot-event-driven-patterns/SKILL.md1Через Skills CLI (Vercel)
npx skills add giuseppe-trisciuoglio/developer-kit --skill spring-boot-event-driven-patterns -a gemini-cli2Командой платформы
gemini skills install https://github.com/giuseppe-trisciuoglio/developer-kit --path plugins/developer-kit-java/skills/spring-boot-event-driven-patternsВручную: положить файлы
.devin/skills/spring-boot-event-driven-patterns/SKILL.mdСтарый путь .windsurf/skills/ тоже читается
Через Skills CLI (Vercel)
npx skills add giuseppe-trisciuoglio/developer-kit --skill spring-boot-event-driven-patterns -a opencodeClaude.ai
Упакуйте папку в zip и загрузите в Settings → Capabilities → Skills
По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов
Из того же набора93
Похожие
Рядом в теме «Бэкенд и API»
Всё по теме «Бэкенд и API» →Вопросы о spring-boot-event-driven-patterns
Как установить spring-boot-event-driven-patterns в Claude?
Выполните npx skills add giuseppe-trisciuoglio/developer-kit --skill spring-boot-event-driven-patterns -a claude-code. Скилл окажется в ~/.claude/skills/spring-boot-event-driven-patterns/SKILL.md.
Что делает spring-boot-event-driven-patterns?
Даёт шаблоны событийной архитектуры для Spring Boot: доменные события, @TransactionalEventListener с фазой AFTER_COMMIT, Kafka-продюсеры и консьюмеры, transactional outbox и обработку сбоев через retry и dead-letter топики.
Что нужно, чтобы скилл заработал с Kafka?
В примерах конфигурации брокер указан как localhost:9092, поэтому для проверки продюсера и консьюмера нужен запущенный Kafka. Скиллу разрешены инструменты Read, Write, Edit и Bash.
Исходный текст
SKILL.md · MIT
---
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):**
```java
@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):**
```java
@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:
```java
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`:
```java
@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:
```java
@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:
```yaml
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:
```java
@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 queues, idempotent handlers:
```java
@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.
### 7. Add Observability
Enable Spring Cloud Sleuth for distributed tracing, monitor metrics.
## Best Practices
- **Use past tense naming**: `ProductCreated` (not `CreateProduct`)
- **Keep events immutable**: All fields should be final
- **Include correlation IDs**: For tracing events across services
- **Use AFTER_COMMIT phase**: Ensures events are published after successful database transaction
- **Implement idempotent handlers**: Handle duplicate events gracefully
- **Add retry mechanisms**: For failed event processing with exponential backoff
- **Implement dead-letter queues**: For events that fail processing after retries
- **Log all failures**: Include sufficient context for debugging
- **Make handlers order-independent**: Event ordering is not guaranteed in distributed systems
- **Batch event processing**: When handling high volumes
- **Monitor event latencies**: Set up alerts for slow processing
## References
- **[dependency-setup.md](references/dependency-setup.md)** — Maven/Gradle dependencies
- **[configuration.md](references/configuration.md)** — Kafka and Spring Cloud Stream configuration
- **[domain-events-design.md](references/domain-events-design.md)** — Domain event design patterns
- **[aggregate-root-patterns.md](references/aggregate-root-patterns.md)** — Aggregate root with event publishing
- **[event-publishing.md](references/event-publishing.md)** — Local and distributed event publishing
- **[event-handling.md](references/event-handling.md)** — Event handling and consumption patterns
- **[outbox-pattern.md](references/outbox-pattern.md)** — Transactional outbox pattern for reliability
- **[testing-strategies.md](references/testing-strategies.md)** — Unit and integration testing approaches
- **[examples.md](references/examples.md)** — Complete working examples
- **[event-driven-patterns-reference.md](references/event-driven-patterns-reference.md)** — Detailed reference documentation
## Constraints and Warnings
- Events published with `@TransactionalEventListener` only fire after transaction commit
- Avoid publishing large objects in events (memory pressure, serialization issues)
- Be cautious with async event handlers (separate threads, concurrency issues)
- Kafka consumers must handle duplicate messages (implement idempotent processing)
- Event ordering is not guaranteed in distributed systems (design handlers to be order-independent)
- Never perform blocking operations in event listeners on the main transaction thread
- Monitor for event processing backlogs (indicate system capacity issues)
## Related Skills
- `spring-boot-security-jwt` — JWT authentication for secure event publishing
- `spring-boot-test-patterns` — Testing event-driven applications
- `aws-sdk-java-v2-lambda` — Event-driven processing with AWS Lambda
- `langchain4j-tool-function-calling-patterns` — AI-driven event processing
© giuseppe-trisciuoglio · MIT · giuseppe-trisciuoglio/developer-kit