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 declared nullable. In Java, annotate the parameter with a runtime-visible @Nullable annotation. Fluxzero recognizes nullable annotations by simple name, so the SDK does not require a specific annotation package.

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:
  • Optional Element Summary

    Optional Elements
    Modifier and Type
    Optional Element
    Description
    boolean
    Disables apply-compatibility checking for this method.
    Controls whether the update should result in a published update, depending on whether the entity was actually modified.
    Controls how the applied update is stored and/or published, and whether publish-only updates advance aggregate state for the owning aggregate type.
  • 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, and whether publish-only updates advance aggregate state for the owning aggregate type. This strategy takes precedence over eventPublication() if explicitly set.
      Returns:
      strategy for persisting and/or publishing the applied update
      Default:
      DEFAULT
    • disableCompatibilityCheck

      boolean disableCompatibilityCheck
      Disables apply-compatibility checking for this method.

      Unless property fluxzero.assert.legal.apply-compatibility is explicitly set to false, Fluxzero verifies that at least one @Apply method is compatible with the current entity state.

      Setting this flag to true exempts this method from that check.

      Default:
      false