Annotation Interface InterceptApply


@Documented @Retention(RUNTIME) @Target(METHOD) public @interface InterceptApply
Indicates that a method should intercept and potentially transform an update before it is applied to an entity.

This annotation is typically used to:

  • Suppress updates that should be ignored
  • Rewrite or correct invalid updates
  • Split a single update into multiple updates

Interceptors are invoked before any @Apply or @AssertLegal methods. If multiple interceptors match, they are invoked recursively until the result stabilizes.

Interceptors can return:

  • The original update (no change)
  • null or void to suppress the update
  • An Optional, Collection, or Stream to emit zero or more updates
  • A different object to replace the update

Method parameters are automatically injected and may include:

  • The current entity (if it exists)
  • Any parent or ancestor entity in the aggregate
  • The update object (if defined on the entity side)
  • Context like Metadata, Message, or User

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

Examples

1. Rewrite a duplicate create into an update (inside the update class)


 @InterceptApply
 UpdateProject resolveDuplicateCreate(Project project) {
     // If this method is invoked, the Project already exists
     return new UpdateProject(projectId, details);
 }
 

2. Suppress a no-op update


 @InterceptApply
 Object ignoreNoChange(Product product) {
     if (product.getDetails().equals(details)) {
         return null; // suppress update
     }
     return this;
 }
 

Note: You typically do not need to implement this kind of check manually if the enclosing @Aggregate or specific @Apply method is configured with IF_MODIFIED. That configuration ensures that no event is stored or published if the entity is not modified.

3. Expand a bulk update into individual operations


 @InterceptApply
 List<CreateTask> explodeBulkCreate() {
     return tasks;
 }
 

4. Recursive interception

If the result of one @InterceptApply method is a new update object, Flux will look for matching interceptors for the new value as well — continuing recursively until no further changes occur.

See Also: