Annotation Interface AssertLegal
Annotation to mark methods or fields that assert whether a command or query is legal, given the current state of an
aggregate.
Can be used in two ways:
- On methods inside a command or query class to perform legality checks directly
- On properties of a command or query class to delegate legality checks to the annotated property’s class
Method-based usage
Annotated methods are invoked after the aggregate and its entities are loaded usingEntity.assertLegal(java.lang.Object)
or Entity.assertAndApply(java.lang.Object)
.
Parameters are injected automatically and may include:
- The command or query object itself
- Any matching entity from the aggregate tree (including parent or grandparent entities)
- Other framework-specific types like
Message
orUser
Note that empty entities (i.e., those with null
values) are not injected unless the parameter is annotated with @Nullable
.
Example: Validate entity does not exist yet
@AssertLegal
void assertNew(Issue issue) {
throw new IllegalCommandException("Issue already exists");
}
Example: Validate entity does exist
@AssertLegal
void assertExists(@Nullable Issue issue) {
if (issue == null) {
throw new IllegalCommandException("Issue not found");
}
}
Property-based usage
When placed on a field of a command or query payload (e.g.,@AssertLegal UserDetails details
),
the framework will look for @AssertLegal
methods or fields within that field’s value.
This enables modular legality checks colocated with the data they validate.
Example
public class UpdateUser {
UserId userId;
@AssertLegal
UserDetails details; // triggers @AssertLegal methods inside UserDetails
}
Return value inspection
If an@AssertLegal
method returns a non-null object, Flux will also inspect that return value for further
@AssertLegal
methods or properties. This allows for deep, composable validation logic.
Ordering
Multiple legality methods may be invoked. Their execution order is determined bypriority()
,
with higher values taking precedence.
Execution timing
By default, checks run immediately during handler execution. You can defer them until after the handler completes (after any @Apply invocations but just before aggregate updates are committed) usingafterHandler()
.- See Also:
-
Optional Element Summary
Optional ElementsModifier and TypeOptional ElementDescriptionboolean
Determines if the legality check should be performed immediately (the default), or when the current handler is done, i.e.: after @Apply and just before the aggregate updates are committed.int
Determines the order of assertions if there are multiple annotated methods. -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final int
static final int
static final int
-
Field Details
-
HIGHEST_PRIORITY
static final int HIGHEST_PRIORITY- See Also:
-
LOWEST_PRIORITY
static final int LOWEST_PRIORITY- See Also:
-
DEFAULT_PRIORITY
static final int DEFAULT_PRIORITY- See Also:
-
-
Element Details
-
priority
int priorityDetermines the order of assertions if there are multiple annotated methods. A method with higher priority will be invoked before methods with a lower priority. UseHIGHEST_PRIORITY
to ensure that the check is performed first.- Default:
0
-
afterHandler
boolean afterHandlerDetermines if the legality check should be performed immediately (the default), or when the current handler is done, i.e.: after @Apply and just before the aggregate updates are committed.- Default:
false
-