Where does business logic live in axon

Im new to CQRS and EventSourcing and Im sure in my first app there are a couple Anti-Patterns though I try to avoid them.

I know I shouldnt do validation in event handlers - events are facts from the past, I cant deny them. I do however small consistency checks there :
Example :

`

@SuppressWarnings("unused")
@EventSourcingHandler
protected void handle(AdminUserRoleRemovedEvent ev){
    if(this.roles.contains(ev.getRole())) this.roles.remove(ev.getRole());
}

`

My question is, where does Validation and Authorization come into play?
Should I check authorization in the servers REST request handler, or in the command handler, passing the user/session context ?
There are some consistency checks that cannot be avoided in a command handler :

`

private Object handleChangeAdminUserLoginCommand(CommandMessage<ChangeAdminUserLoginCommand> commandMessage, UnitOfWork unitOfWork){
    MetaData commandMetaData = MetaData.from(ImmutableMap.of("command", commandMessage));
    ChangeAdminUserLoginCommand caulc = commandMessage.getPayload();
    Assert.notEmpty(caulc.getNewLogin(), "Login cannot be empty");

    AdminUserAggregate adminUser = eventStore.getAdminUserRepository().load(caulc.getIdentifier());

    if(claimLogin(caulc.getNewLogin())){
        registerUnitOfWorkListenerToCancelClaimingLogin(caulc.getNewLogin(), unitOfWork);
        registerUnitOfWorkListenerToFreeClaimedLogin(adminUser.getLogin(), unitOfWork);
        adminUser.changeLogin(caulc.getNewLogin(), commandMetaData);
        return new AdminUser(adminUser);

    } else {
        throw new AdminUserLoginAlreadyTakenException(caulc.getNewLogin());
    }

}

`

Also, what is the recommended way to get the aggregate identifier in event handlers ? the EventMessage class doesnt expose the ID, so for now I use a hackaround to get it. Do I really have to add an Identifier field to every event in my system ?

`

public void handleEvent(EventMessage eventMessage, BaseEvent baseEvent) {
    Class<?> eventClass = eventMessage.getPayloadType();
    Object aggregateIdentifier = ((GenericDomainEventMessage)eventMessage).getAggregateIdentifier(); // TODO : this is a nasty hack

`

Im new to CQRS and EventSourcing and Im sure in my first app there are a couple Anti-Patterns though I try to avoid them.

I know I shouldnt do validation in event handlers - events are facts from the past, I cant deny them. I do however small consistency checks there :
Example :

`

@SuppressWarnings("unused")
@EventSourcingHandler
protected void handle(AdminUserRoleRemovedEvent ev){
    if(this.roles.contains(ev.getRole())) this.roles.remove(ev.getRole());
}

`

The events in event sourcing handlers have been generated by the aggregate itself. I currently exclusively make all consistency checks and decisions in the command handler, and use the event handlers for state change only.

My question is, where does Validation and Authorization come into play?
Should I check authorization in the servers REST request handler, or in the command handler, passing the user/session context ?

Authorization can be done in many places.
a) At the REST request handler (e.g., spring security) making sure that authentication happened.
b) If you have OAuth scopes … have not done that myself so far … probably best to enforce access rules in the handler or before it as well.
b) using RBAC … probably use Spring security at the handlers as well.

Now it gets interesting… once you passed the barrier of allowing to use the

There are some consistency checks that cannot be avoided in a command handler :

`

private Object handleChangeAdminUserLoginCommand(CommandMessage<ChangeAdminUserLoginCommand> commandMessage, UnitOfWork unitOfWork){
    MetaData commandMetaData = MetaData.from(ImmutableMap.of("command", commandMessage));
    ChangeAdminUserLoginCommand caulc = commandMessage.getPayload();
    Assert.notEmpty(caulc.getNewLogin(), "Login cannot be empty");

    AdminUserAggregate adminUser = eventStore.getAdminUserRepository().load(caulc.getIdentifier());

    if(claimLogin(caulc.getNewLogin())){
        registerUnitOfWorkListenerToCancelClaimingLogin(caulc.getNewLogin(), unitOfWork);
        registerUnitOfWorkListenerToFreeClaimedLogin(adminUser.getLogin(), unitOfWork);
        adminUser.changeLogin(caulc.getNewLogin(), commandMetaData);
        return new AdminUser(adminUser);

    } else {
        throw new AdminUserLoginAlreadyTakenException(caulc.getNewLogin());
    }

}

`

I am not entirely sure why you are working with UnitOfWork explicitly here (please explain, I am curious, not critical here). But if you go for the annotated syntax you can do:

`
@CommandHandler
private Object handleChangeAdminUserLoginCommand(ChangeAdminUserLoginCommand command, Metadata metaData, UnitOfWork unitOfWork){

`

I would argue that the command handler is the only place where yu need consistency checks. How I understand it, the command handler decides if and how the state change tekes place.
The event contains all information needed to perform the state change with as little calcualtion as possible (and it potentially contains additional information required to update query models).

At least in the aggregate, event handlers are dumb and only apply the state change.

Outside of aggregates event handlers may have to perform additional checks and actions.

Also, what is the recommended way to get the aggregate identifier in event handlers ? the EventMessage class doesnt expose the ID, so for now I use a hackaround to get it. Do I really have to add an Identifier field to every event in my system ?

AFAIK it is recommended to manually have a field for it in the respective message and to set it accordingly.

Dominic

Sorry, did not finish my sentence …

Now it gets interesting… once you passed the barrier of allowing to use the request handler, reading access you have to decide however to do it. Axon ignores that area. With commands, you can specify an authorization command interceptor. That can block all commands according to your logic.

If the authorization is connected more deeply with your domain, continue on in the respective handlers.

Dominic