Define event handlers in Java

Event handlers process events by creating a new aggregate or updating an existing one. The Eventuate client framework for Java supports a number of ways to implement event handlers. The simplest approach is to use the high-level API.

High-level event handler API for Java

The high-level API hides a lot of the boilerplate code that you would otherwise have to write. When using this API you define one or more event handler Spring/Micronaut beans. Each bean defines one or more event handler methods, one for each type of event that the handler processes. The framework subscribes to the events and dispatches each event to the appropriate event handler method.

Here is an example of an event handler class. It defines two methods, debitAccount(), which handles MoneyTransferCreatedEvents, and creditAccount, which handles DebitRecordedEvents.

@EventSubscriber(id="accountEventHandlers")
public class AccountWorkflow {

  @EventHandlerMethod
  public CompletableFuture<?> debitAccount(EventHandlerContext<MoneyTransferCreatedEvent> ctx) {
    MoneyTransferCreatedEvent event = ctx.getEvent();
    BigDecimal amount = event.getDetails().getAmount();
    Aggregate.EntityId transactionId = ctx.getEntityId();

    Aggregate.EntityId fromAccountId = event.getDetails().getFromAccountId();

    return ctx.update(Account.class, fromAccountId,
                          new DebitAccountCommand(amount, transactionId));
  }

  @EventHandlerMethod
  public CompletableFuture<?> creditAccount(EventHandlerContext<DebitRecordedEvent> ctx) {
    ...
  }
}

The @EventSubscriber annotation specifies the name of the subscription.

Each event handler method is annotated with @EventHandlerMethod. An event handler method has a single parameter of type EventHandlerContext, a generic interface, which is parameterized by the event type. It has methods that provide access to the event as well as metadata such as the type and identity of the aggregate that published the event. It also defines save() and update() methods that the event handler uses to create or update an aggregate.

An event handler method can return either a CompletableFuture<?> or void.

Low-level API

The low-level API is much more flexible but requires you to write much more code. It consists of an EventuateAggregateStore interface, which you can inject into your event handling code.

Spring

class MyEventHandlingCode {

  @Autowired
  private EventuateAggregateStore EventuateAggregateStore;
  ...
}

Micronaut

class MyEventHandlingCode {

  @Inject
  private EventuateAggregateStore EventuateAggregateStore;
  ...
}

EventuateAggregateStore has a subscribe() method. This method creates a durable named subscription to one or more event types:

interface EventStoreSubscriptionManagement {

  CompletableFuture<?> subscribe(String subscriberId, Map<String, Set<String>> aggregatesAndEvents, SubscriberOptions subscriberOptions,
                                    Function<DispatchedEvent<Event>, CompletableFuture<?>> handler);

}

The subscriptionId parameter specifies the name of the subscription and the events to subscribe to. The aggregatesAndEvents specifies a set of event types for each aggregate type. Since the process of establishing the subscription is asynchronous, it returns an CompletableFuture<?>. The handler is invoked for each event.


Stay in touch
Copyright © 2021 Eventuate, Inc • All rights reserved.