Annotation Interface Apply
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, Flux 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 itsMetadata
- 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:
-
Optional Element Summary
Optional ElementsModifier and TypeOptional ElementDescriptionControls 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.
-
Element Details
-
eventPublication
EventPublication eventPublicationControls 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 publicationStrategyControls how the applied update is stored and/or published. This strategy takes precedence overeventPublication()
if explicitly set.- Returns:
- strategy for persisting and/or publishing the applied update
- Default:
DEFAULT
-