SimpleDomainEventPublisher.java
package com.reallifedeveloper.common.domain.event;
import java.util.ArrayList;
import java.util.List;
/**
* A publisher of domain events that holds subscribers in a list. Publishing is handled
* synchronously; to handle events asynchronously, a subscriber could send a message to
* a message queue or store the event for later processing.
* <p>
* The idea behind this publisher is that it will be configured once and for all, for
* example using Spring:
*
* <pre>
* <bean class="th.co.edge.domain.event.SimpleDomainEventPublisher">
* <constructor-arg>
* <list>
* <bean class="com.foo.FooSubscriber" />
* <bean class="com.foo.BarSubscriber" />
* </list>
* </constructor-arg>
* </bean>
* </pre>
* <p>
* The publisher can then be injected in the classes that need to publish events:
*
* <pre>
* @Autowired
* private DomainEventSubscriber eventSubscriber;
* </pre>
* <p>
* Used this way in a normal enterprise application, several threads may call the
* {@link #publish(DomainEvent)} method simultaneously, so the subscribers should
* be thread safe.
*
* @author RealLifeDeveloper
*/
public final class SimpleDomainEventPublisher implements DomainEventPublisher {
private List<DomainEventSubscriber<? extends DomainEvent>> subscribers = new ArrayList<>();
/**
* Creates a new {@code SimpleDomainEventPublisher} with no subscribers registered.
* <p>
* Use the {@link #subscribe(DomainEventSubscriber)} to add subscribers.
*/
public SimpleDomainEventPublisher() {
super();
}
/**
* Creates a new {@code SimpleDomainEventPublisher} with a number of subscribers
* registered to be notified when events are published.
*
* @param subscribers a list of subscribers to notify when events are published
* @throws IllegalArgumentException if {@code subscribers} is {@code null}
*/
public SimpleDomainEventPublisher(List<DomainEventSubscriber<? extends DomainEvent>> subscribers) {
if (subscribers == null) {
throw new IllegalArgumentException("subscribers must not be null");
}
this.subscribers = new ArrayList<>(subscribers);
}
/**
* Publishes a domain event, i.e., calls the {@link DomainEventSubscriber#handleEvent(DomainEvent)}
* method for each registered subscriber.
*
* @param event the domain event to publish
* @throws IllegalArgumentException if {@code event} is {@code null}
*/
@Override
public void publish(DomainEvent event) {
if (event == null) {
throw new IllegalArgumentException("event must not be null");
}
for (DomainEventSubscriber<? extends DomainEvent> subscriber : subscribers) {
if (subscriber.eventType().isAssignableFrom(event.getClass())) {
@SuppressWarnings("unchecked")
DomainEventSubscriber<DomainEvent> s = (DomainEventSubscriber<DomainEvent>) subscriber;
s.handleEvent(event);
}
}
}
/**
* Registers an event handler with this publisher.
*
* @param subscriber the event handler to register
* @throws IllegalArgumentException if {@code subscriber} is {@code null}
*/
@Override
public void subscribe(DomainEventSubscriber<? extends DomainEvent> subscriber) {
if (subscriber == null) {
throw new IllegalArgumentException("subscriber must not be null");
}
subscribers.add(subscriber);
}
}