Annotation Interface Apply


Indicates that a method or constructor applies an update to an entity, or creates or deletes an entity.

An @Apply method defines how a specific update modifies an entity. This update is typically the payload of a command or other message expressing intent. Once validated and applied, the update may be published and/or stored as an event, depending on the publication configuration.

@Apply can be placed:

  • On a method inside the update class (e.g. UpdateProduct#apply(Product)), which receives the current state of the entity and returns the updated version
  • On a method or static factory in the entity class itself (e.g. Product#update(UpdateProduct)), which describes how the entity processes a given update
  • On a constructor or static method of the entity, if the update creates a new instance

For deletions, returning null signals that the entity should be removed.

When the entity is part of a larger aggregate, Fluxzero automatically routes the update to the correct entity instance using matching identifier fields, typically annotated with EntityId.

@Apply methods are also used during event sourcing to reconstruct an entity's state from past updates.

Method parameters are injected automatically. Supported parameters include:

  • The current entity instance (for non-static apply methods)
  • Any parent, grandparent, or other ancestor entity in the aggregate hierarchy
  • The update object itself
  • The full Message or its Metadata
  • Other context such as the User performing the update

Note that empty entities (where the value of the entity is null) are not injected unless the parameter is annotated with @Nullable.

Examples

1. Creating a new entity from an @Apply method inside the update class

@Apply
Issue create() {
    return Issue.builder()
                .issueId(issueId)
                .count(1)
                .status(IssueStatus.OPEN)
                .details(issueDetails)
                .firstSeen(lastSeen)
                .lastSeen(lastSeen)
                .build();
}

2. Updating an entity with a new state

@Apply
Product apply(Product product) {
    return product.toBuilder().details(details).build();
}

3. Deleting an entity

@Apply
Product apply(Product product) {
    return null;
}

4. Defining apply methods inside the entity class

@Apply
static Product create(CreateProduct update) {
    return Product.builder()
                  .productId(update.getProductId())
                  .details(update.getDetails())
                  .build();
}

@Apply
Product update(UpdateProduct update) {
    return this.toBuilder().details(update.getDetails()).build();
}

@Apply
Product delete(DeleteProduct update) {
    return null;
}

Routing example with aggregates and nested entities

@Aggregate
class ProductCategory {
    String categoryId;

    @Member
    List<Product> products;
}
Updates targeting `Product` will automatically be routed based on `@EntityId` inside `Product`.
See Also:
  • Element Details

    • eventPublication

      EventPublication eventPublication
      Controls whether the update should result in a published update, depending on whether the entity was actually modified.

      This overrides the default from the enclosing aggregate, if set.

      Returns:
      update publication behavior
      Default:
      DEFAULT
    • publicationStrategy

      EventPublicationStrategy publicationStrategy
      Controls how the applied update is stored and/or published. This strategy takes precedence over eventPublication() if explicitly set.
      Returns:
      strategy for persisting and/or publishing the applied update
      Default:
      DEFAULT