-
Notifications
You must be signed in to change notification settings - Fork 0
Async and Filtering Events π¦
Table Of Contents
By default, Spring events are synchronous, meaning that the publisher thread blocks until all listeners interested in a particular event have finished processing the event.
What if we have a listener that takes too long to get executed an publishing synchronously ?
Ref.:[1]The solution is to make the event listener running in Async mode. To do so, we have to annotate the listener with @Async annotation ( @EnableAsync is required on top of the Spring configuration).
Please note that, the usage of @Async comes with its limitations :
- Cannot publish event by returning value.
- Use ApplicationEventPublisher.publish() if any.
- Exceptions are not propagated to the caller.
- Use AsyncUncaughExceptionHandler interface if any.
An external call is really slow and it doesn't make sense to block the whole use case. Executing this call as an event asynchronously is the best approach.
Ref.:[1]import lombok.RequiredArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class AnalyticsCustomerRegisteredListener {
private final AnalyticsService analyticsService;
@EventListener
@Async
public void onRegisterEvent(CustomerRegisteredEvent event) {
analyticsService.registerNewCustomer(event.getCustomer());
}
}
Let say we want an event listener to be triggered only if some condition is satisfiable. The intuitive solution is to add an if statement to check a certain condition.
public class MyListener {
@EventListener
public void onEvent(Object o) {
if(condition) {..}
}
}
However, overusing conditionals statement results in code that is more complex and difficult to maintain.
We can avoid this by fine-tuning those conditions with @EventListener and Spring Expression Language (SpEL).
@EventListener provides a conditional attribute that accepts SpEL expression. The event will be handled if the expression evaluates :
- The 'Boolean' : true
- One of Strings : "true", "on", "yes", "1"
- The default expression is empty String : "" (meaning the event is always handled)
Examples
- #event : reference to an event
- #event.customer.type eq 'b2c'
In the following use case, the purpose is to run a promotion for all new customers who have signed up for the newsletter.
import lombok.RequiredArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class PromotionListeners {
private final PromotionService promotionService;
@EventListener(condition = "#event.customer.newsletter")
public void onRegistrationEvent (CustomerRegisteredEvent event) {
promotionService.applyPromotion(event.getCustomer());
}
}
"The higher we soar the smaller we appear to those who cannot fly."
[Friedrich Nietzsche]