Warning / Info messages

In addition to event generation, command handlers can also return messages, that can be use to give info / warning to the caller.

For instance, let’s say that we want to issue a warning message when a Withdraw command put account balance under 0.

public class BankCommandHandler implements CommandHandler<String, Account, BankCommand, BankEvent, List<String>, Connection> {
    @Override
    public CompletionStage<Either<String, Events<BankEvent, List<String>>>> handleCommand(
            Connection transactionContext,
            Option<Account> previousState,
            BankCommand command) {
        return CompletableFuture.supplyAsync(() -> switch (command) {
            case BankCommand.Withdraw withdraw -> this.handleWithdraw(previousState, withdraw);
            case BankCommand.Deposit deposit -> this.handleDeposit(previousState, deposit);
            case BankCommand.OpenAccount openAccount -> this.handleOpening(openAccount);
            case BankCommand.CloseAccount close -> this.handleClosing(previousState, close);
        });
    }

    //...

    private Either<String, Events<BankEvent, List<String>>> handleWithdraw(
            Option<Account> previousState,
            BankCommand.Withdraw withdraw) {
        return previousState.toEither("Account does not exist")
            .flatMap(previous -> {
                BigDecimal newBalance = previous.balance.subtract(withdraw.amount);
                List<String> messages = List();
                if(newBalance.compareTo(BigDecimal.ZERO) < 0) {
                    messages = messages.push("Overdrawn account");
                }
                return Right(Events.events(messages, new BankEvent.MoneyWithdrawn(withdraw.account, withdraw.amount)));
            });
    }
}

We needed to replace CommandHandler’s Tuple0 parameter by a List<String> well suited to represent basic messages. This implies to change this Message parameter from Tuple0 to List<Message> everywhere in the application.