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.