Sorry about all the questions being posted, I’ve been working on a proof-of-concept and I’m trying to understand the best way to construct a project based on Axon. This time has to do with validation.
I’ve been using Spring-based JSR-303 validation to ensure the consistency of data provided on API requests and commands. For example, I have this data structure for a create user request:
data class NewUserRequest(
@Length(min = 4, max = 30)
val username: String?,
@Email
val emailAddress: String?,
@NotEmpty
@Length(min = 1, max = 50)
val firstName: String,
@NotEmpty
@Length(min = 1, max = 50)
val lastName: String
)
And the command to create a new user:
data class CreateUserCommand(
@NotBlank
@Size(min = 6, max = 40)
@Unique(byAggregate = User::class, mode = CrudMode.Create)
val username: String,
@NotBlank
@Size(min = 1, max = 40)
val firstName: String,
@NotBlank
@Size(min = 1, max = 40)
val lastName: String,
@Email
@Unique(byAggregate = User::class, mode = CrudMode.Create)
val emailAddress: String?
): Command {
val id: UUID
@RoutingKey
get() = UUID.randomUUID()
}
I use a parameter resolver to run all of the constraint validators and generate an Errors object if any violations were found. The command handler injects this errors object and, if an error exists, throws an exception:
@CommandHandler
constructor(command: CreateUserCommand, validationErrors: Errors): this() {
handleValidationErrors(validationErrors)
applyEvent(NewUserEvent(command.id, command.username, command.firstName, command.lastName, command.emailAddress))
}
This all works great, but the API ends up throwing a 500 error because the exception thrown by the commandGateway is an AxonException, and the cause chain doesn’t appear to preserve original exception type. Is there a way to determine the source exception type? Or is it better to not validate at all in the command handlers and always validate in the API? This gives me pause simply because I could have multiple places in code that trigger the command, and all of them would now need the same validation logic.