Interface EventExceptionHandler
When a handler throws an exception, the event bus will invoke this handler with full context information, allowing for detailed logging, monitoring, or recovery actions. The exception handler prevents one failing handler from breaking the entire event pipeline.
The exception handler is invoked synchronously in the same thread where the exception occurred, regardless of whether the failing handler was executing synchronously or asynchronously.
Key Characteristics
- Invoked for every handler exception, providing full error context
- Executed synchronously in the same thread as the failing handler
- Other handlers continue to execute even after one fails
- Exception handler failures are logged but do not propagate
Common Use Cases
- Logging handler failures with detailed context information
- Sending error metrics to monitoring systems
- Alerting administrators of critical handler failures
- Recording handler reliability statistics
- Implementing retry logic for transient failures
Example: Basic Logging
EventExceptionHandler handler = (event, exception, handlerId) -> {
logger.error("Handler {} failed while processing event {}: {}",
handlerId,
event.getClass().getSimpleName(),
exception.getMessage(),
exception);
};
EventBus eventBus = EventBus.builder()
.exceptionHandler(handler)
.build();
Example: Metrics and Monitoring
EventExceptionHandler handler = (event, exception, handlerId) -> {
// Record exception metrics
metrics.incrementCounter("event.handler.errors",
"event_type", event.getClass().getSimpleName(),
"exception_type", exception.getClass().getSimpleName()
);
// Send to monitoring system
monitoring.recordException(handlerId, event, exception);
// Log with context
logger.error("Handler failure", exception);
};
Example: Critical Error Alerting
EventExceptionHandler handler = (event, exception, handlerId) -> {
logger.error("Handler {} failed processing {}", handlerId, event, exception);
// Alert for critical events
if (event instanceof CommandPreRegistrationEvent) {
alertService.sendAlert(
"Critical handler failure in command registration",
"Handler ID: " + handlerId + "\nException: " + exception.getMessage()
);
}
// Store for later analysis
errorRepository.save(new HandlerError(handlerId, event, exception));
};
Example: Conditional Retry Logic
EventExceptionHandler handler = (event, exception, handlerId) -> {
logger.warn("Handler {} failed, checking for retry", handlerId, exception);
// Retry for transient failures
if (exception instanceof TransientException) {
EventSubscription<?> subscription = findSubscription(handlerId);
if (subscription != null && shouldRetry(handlerId)) {
logger.info("Retrying handler {}", handlerId);
scheduler.schedule(() -> {
try {
subscription.handler().accept(event);
} catch (Exception e) {
logger.error("Retry failed for handler {}", handlerId, e);
}
}, 1, TimeUnit.SECONDS);
}
}
};
Example: Handler Reliability Tracking
Map<UUID, HandlerStats> handlerStats = new ConcurrentHashMap<>();
EventExceptionHandler handler = (event, exception, handlerId) -> {
// Track failure statistics
handlerStats.computeIfAbsent(handlerId, id -> new HandlerStats())
.recordFailure(exception);
HandlerStats stats = handlerStats.get(handlerId);
logger.error("Handler {} failed (failures: {}, success rate: {}%)",
handlerId, stats.getFailureCount(), stats.getSuccessRate());
// Disable problematic handlers
if (stats.getSuccessRate() < 50.0) {
logger.warn("Disabling unreliable handler {}", handlerId);
eventBus.unregister(handlerId);
}
};
Best Practices
- Always log exceptions with sufficient context for debugging
- Keep exception handler logic fast and simple
- Avoid throwing exceptions from the exception handler itself
- Consider async logging/metrics to avoid blocking
- Use structured logging for better searchability
Isolation Guarantee: When an exception occurs, the exception handler is called, but the event pipeline continues. Other handlers will still execute even if one handler fails.
- Since:
- 1.0
- See Also:
-
Method Summary
Modifier and TypeMethodDescription<E extends Event>
voidhandle(E event, Throwable exception, EventSubscription<E> subscription) Handles an exception that occurred during event handler execution.
-
Method Details
-
handle
Handles an exception that occurred during event handler execution.This method is called synchronously whenever a handler throws an exception. Implementations should be fast and should not throw exceptions themselves.
- Parameters:
event- the event that was being processed when the exception occurredexception- the exception that was thrown by the handlersubscription- the unique identifier of the handler that threw the exception
-