Domain Events
A domain event is used to represent something that happened in the domain.
It happened in the past and is of interest to the business.
Characteristics
Past-tense
A domain event always represent something that happened in the past. Its name must be in the past tense and be based upon the ubiquitous language.
Contents
A domain event can be as little as just a name. More often, it will contain values and identifiers that represent the relevant state at the time the event happened. That state should be minimized and the receivers should query the model to access additional information if necessary.
Immutable
As they represent something in the past, domain events must be immutable. As such they can only contain immutable objects like value objects, primitive types, strings, etc…
Simple
Domain events are first and foremost about communication, within the system but also with other systems. A domain event should therefore be kept as simple as possible as be easy to serialize.
Declaration
In the business framework a domain event is a special sub-type of value object. To create a domain event with the business framework, you have two alternatives.
Extend the BaseDomainEvent
class:
public class SomeDomainEvent extends BaseDomainEvent {
private String attribute1;
private String attribute2;
public SomeDomainEvent(String attribute1, String attribute2) {
this.attribute1 = attribute1;
this.attribute2 = attribute2;
}
// Other methods
}
By extending BaseDomainEvent
, you will have a default implementation of the
equals()
and hashCode()
methods, consistent with the definition of a value object. A toString()
is also provided by default.
Implement the DomainEvent
interface:
public class SomeDomainEvent implements DomainEvent {
private String attribute1;
private String attribute2;
public SomeDomainEvent(String attribute1, String attribute2) {
this.attribute1 = attribute1;
this.attribute2 = attribute2;
}
public int hashCode() {
// TODO: implement based on all attributes
}
public boolean equals() {
// TODO: implement based on all attributes
}
// Other methods
}
Implementing DomainEvent
allows you to fully control the inheritance of your
event. However, you will have to implement equals()
and hashCode()
methods yourself, consistently with the definition
of a value object (i.e. based on all the event attributes).
Usage
Events are published and received synchronously.
Publishing events
To publish an event, inject EventService
where required:
public class SomeClass {
@Inject
private EventService eventService;
public void someMethod() {
eventService.fire(new SomeDomainEvent("val1", "val2"));
}
}
Subscribing to events
To subscribe to an event, simply create a class implementing the EventHandler
interface
with the class of the event to subscribe to as generic parameter:
public class SomeEventHandler implements EventHandler<SomeDomainEvent> {
@Override
public void handle(SomeDomainEvent someDomainEvent) {
// handle event
}
}
Multiple handlers can be declared for the same type of event, allowing any part of the system to react to any event that happened in the domain.
If you have an event hierarchy, you can subscribe at any level in this hierarchy. Subscribing to a particular event class implies that you will receive events of this class and all its sub-classes.