Class FlexAggregate<ID,​AGGREGATE_TYPE extends FlexAggregate<ID,​AGGREGATE_TYPE>>

  • Type Parameters:
    ID - The id type for the aggregate id
    AGGREGATE_TYPE - the type of the aggregate
    All Implemented Interfaces:
    Aggregate<ID,​AGGREGATE_TYPE>

    public abstract class FlexAggregate<ID,​AGGREGATE_TYPE extends FlexAggregate<ID,​AGGREGATE_TYPE>>
    extends Object
    implements Aggregate<ID,​AGGREGATE_TYPE>
    Simple, easy and opinionated aggregate that allows you to apply events that don't have any requirements with regards to inheritance (i.e. you can use Records) in combination with an FlexAggregateRepository
    Events
    
         public record OrderAdded(OrderId orderId, CustomerId orderingCustomerId, long orderNumber) {
         }
    
         public static class OrderAccepted {
             public final OrderId orderId;
    
             public OrderAccepted(OrderId orderId) {
                 this.orderId = orderId;
             }
         }
     
    New Aggregate instance
    The method that creates a new aggregate instance may be a static method that returns a EventsToPersist instance:
    
     unitOfWorkFactory.usingUnitOfWork(unitOfWork -> {
          var eventsToPersist = Order.createNewOrder(orderId, CustomerId.random(), 123);
          repository.persist(eventsToPersist);
      });
     
    Where the createNewOrder static methods looks like:
    
         public static EventsToPersist<OrderId> createNewOrder(OrderId orderId,
                                                               CustomerId orderingCustomerId,
                                                               int orderNumber) {
             FailFast.requireNonNull(orderId, "You must provide an orderId");
             FailFast.requireNonNull(orderingCustomerId, "You must provide an orderingCustomerId");
             return initialAggregateEvents(orderId, new OrderAdded(orderId, orderingCustomerId, orderNumber));
         }
     
     
    Aggregate command methods
    Each individual command method MUST also return a EventsToPersist instance that can will usually be use in in a call to FlexAggregateRepository.persist(EventsToPersist)
    
     FlexAggregateRepository<OrderId, Order> repository =
                       FlexAggregateRepository.from(
                            eventStores,
                            standardSingleTenantConfigurationUsingJackson(
                                 AggregateType.of("Orders"),
                                 createObjectMapper(),
                                 AggregateIdSerializer.serializerFor(OrderId.class),
                                 IdentifierColumnType.UUID,
                                 JSONColumnType.JSONB),
                             unitOfWorkFactory,
                             OrderId.class,
                             Order.class
                            );
    
     unitOfWorkFactory.usingUnitOfWork(unitOfWork -> {
          var order = repository.load(orderId);
          var eventsToPersist = order.accept();
          repository.persist(eventsToPersist);
      });
     
     
    And where the accept() command method looks like this:
    
         public EventsToPersist<OrderId> accept() {
             if (accepted) {
                 return noEvents();
             }
             return events(new OrderAccepted(aggregateId()));
         }
     

    Command method chaining
    Command methods can be chained like this:
    
             unitOfWorkFactory.usingUnitOfWork(unitOfWork -> {
                 var eventsToPersist = Order.createNewOrder(orderId, CustomerId.random(), 123);
                 eventsToPersist = eventsToPersist.append(new Order().rehydrate(eventsToPersist).addProduct(productId, 10));
                 repository.persist(eventsToPersist);
             });
     
    Aggregate event handling methods

    When an aggregate is loaded from the EventStore using the FlexAggregateRepository, e.g. using FlexAggregateRepository.load(Object) or FlexAggregateRepository.tryLoad(Object), the repository will return an FlexAggregate instance that has had all events returned from the EventStore applied to it.
    What happens internally is that the FlexAggregateRepository.load(Object) method will call rehydrate(AggregateEventStream), which in-order will call applyRehydratedEventToTheAggregate(Object) for each event returned from the EventStore.
    You can either choose to implement the event matching using instanceof:

    {@code
    See Also:
    FlexAggregateRepository