L’interface est localisée ; les présentations et documents des Skills sont traduits automatiquement par IA dans votre langue. Le code, les commandes, chemins et termes techniques restent en version originale, et le document de l’auteur fait foi.
Explorer les Skills
Productivité · SKILL.md

spring-events

spring-events

Spring Application Events for Spring Boot 3.x. Covers ApplicationEventPublisher, @EventListener, @TransactionalEventListener, custom events, async events, and event-driven architecture patterns. USE WHEN: user mentions "spring events", "ApplicationEventPublisher", "@EventListener", "@TransactionalEventListener", "event-driven Spring", "domain events" DO N…

Independent GitHub snapshot · Automated classification · Original documentation governs

Documentation de la Skill

GitHub

name: spring-events description: | Spring Application Events for Spring Boot 3.x. Covers ApplicationEventPublisher, @EventListener, @TransactionalEventListener, custom events, async events, and event-driven architecture patterns.

USE WHEN: user mentions "spring events", "ApplicationEventPublisher", "@EventListener", "@TransactionalEventListener", "event-driven Spring", "domain events"

DO NOT USE FOR: external messaging - use spring-amqp or spring-kafka, distributed events - use messaging systems allowed-tools: Read, Grep, Glob, Write, Edit

Spring Application Events

Quick Start

// Custom Event (POJO - preferred)
public record OrderCreatedEvent(
    Long orderId,
    Long customerId,
    BigDecimal totalAmount,
    Instant createdAt
) {}

// Publisher
@Service
@RequiredArgsConstructor
public class OrderService {

    private final ApplicationEventPublisher eventPublisher;

    @Transactional
    public Order createOrder(CreateOrderRequest request) {
        Order order = orderRepository.save(new Order(request));
        eventPublisher.publishEvent(new OrderCreatedEvent(
            order.getId(), order.getCustomerId(),
            order.getTotalAmount(), order.getCreatedAt()
        ));
        return order;
    }
}

// Listener
@Component
@Slf4j
public class OrderEventListener {

    @EventListener
    public void handleOrderCreated(OrderCreatedEvent event) {
        log.info("Order created: {}", event.orderId());
    }
}

@EventListener

@Component
public class EventListeners {

    // Basic listener
    @EventListener
    public void handleOrderCreated(OrderCreatedEvent event) {
        log.info("Processing order: {}", event.orderId());
    }

    // Conditional listener
    @EventListener(condition = "#event.totalAmount > 1000")
    public void handleLargeOrder(OrderCreatedEvent event) {
        notifyManager(event);
    }

    // Ordered execution
    @EventListener
    @Order(1)  // Executed first
    public void validateOrder(OrderCreatedEvent event) { }

    @EventListener
    @Order(2)  // Executed second
    public void processOrder(OrderCreatedEvent event) { }

    // Multiple event types
    @EventListener({OrderCreatedEvent.class, OrderUpdatedEvent.class})
    public void handleOrderChange(Object event) { }
}

Event Chain (Publish New Event from Listener)

@EventListener
public NotificationEvent handleOrderCreated(OrderCreatedEvent event) {
    return new NotificationEvent(event.customerId(), "Order created!");
}

@EventListener
public Collection<Object> handleOrderShipped(OrderShippedEvent event) {
    return List.of(
        new NotificationEvent(event.customerId(), "Order shipped!"),
        new AnalyticsEvent("order_shipped", event.orderId())
    );
}

Custom Events

// Generic event
public class EntityEvent<T> {
    private final T entity;
    private final EventType type;
    private final Instant timestamp = Instant.now();

    public enum EventType { CREATED, UPDATED, DELETED }
}

// Generic publisher
@Component
public class EntityEventPublisher {
    private final ApplicationEventPublisher publisher;

    public <T> void publishCreated(T entity) {
        publisher.publishEvent(new EntityEvent<>(entity, EventType.CREATED));
    }
}

// Typed listener
@EventListener
public void handleUserEvent(EntityEvent<User> event) {
    switch (event.getType()) {
        case CREATED -> handleUserCreated(event.getEntity());
        case UPDATED -> handleUserUpdated(event.getEntity());
    }
}

Full Reference: See transactional.md for @TransactionalEventListener, Async Events.


@TransactionalEventListener

// Execute AFTER transaction commit (default)
@TransactionalEventListener
public void handleAfterCommit(OrderCreatedEvent event) {
    emailService.sendOrderConfirmation(event.orderId());
}

// Execute AFTER rollback
@TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
public void handleAfterRollback(OrderCreatedEvent event) {
    alertService.notifyRollback(event);
}

// Execute BEFORE commit
@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
public void handleBeforeCommit(OrderCreatedEvent event) {
    validateOrderBeforeCommit(event);
}

// Fallback if no transaction
@TransactionalEventListener(fallbackExecution = true)
public void handleWithFallback(OrderCreatedEvent event) { }

Full Reference: See patterns.md for Domain Events, Aggregate Root, Event Store.


Best Practices

  • ✅ Use @TransactionalEventListener for side effects
  • ✅ Use @Async for non-critical operations
  • ✅ Implement retry for fallible listeners
  • ✅ Use immutable events (records)
  • ✅ Define order with @Order if needed
  • ❌ Don't modify state in sync listeners
  • ❌ Don't assume execution order without @Order

Production Checklist

  • Event classes immutabili
  • TransactionalEventListener for external calls
  • Async for non-critical operations
  • Error handling implemented
  • Retry for transient operations
  • Monitoring events

When NOT to Use This Skill

  • Distributed events - Use spring-kafka or spring-amqp
  • Guaranteed delivery - Use messaging systems
  • Event sourcing - Consider Axon Framework

Common Pitfalls

ErrorCauseSolution
Listener not executedMissing @ComponentAdd annotation
Event lost on rollbackUsing @EventListenerUse @TransactionalEventListener
DeadlockSync listener calls same serviceUse @Async
Exception hiddenAsync voidImplement error handler

Anti-Patterns

Anti-PatternProblemSolution
Sync events in transactionLong transactionsUse @Async or @TransactionalEventListener
Circular event publishingInfinite loopGuard with flags
Heavy processing in syncBlocks publisherUse async listeners
Modifying event after publishShared state issuesMake events immutable

Quick Troubleshooting

ProblemDiagnosticFix
Listener not invokedCheck @EventListenerVerify component scanned
Transaction not committedCheck event phaseUse AFTER_COMMIT
Async not workingCheck @EnableAsyncAdd to config
Order mattersListeners randomUse @Order

Reference Files

FileContent
transactional.md@TransactionalEventListener, Async Events, Lifecycle
patterns.mdDomain Events, Aggregate Root, Event Store

External Documentation

Skills enregistrées