Custom command gateway not returning aggregate from constructor

I have a question regarding returning values from a method on a custom command gateway. Briefly, it appears I cannot return the aggregate directly from its constructor. When I try this, the aggregate is constructed but the command gateway method always returns null.

In detail, say I have a simple custom command gateway :

public interface MyCommandGateway {
MyAggregate createMyAggregate(CreateMyAggregateCommand command);
}

In my aggregate, I attach the command handler to the constructor :

public class MyAggregate extends AbstractAnnotatedAggregateRoot {
@AggregateIdentifier
private MyAggregateId myAggregateId;

@CommandHandler
public MyAggregate(CreateMyAggregateCommand command) {
apply(new MyAggregateCreatedEvent(command.myAggregateId()));
}

@EventHandler
protected void handle(MyAggregateCreatedEvent event) {
myAggregateId = event.myAggregateId();

}
}

I am using the default command bus and event bus. I’m using Spring to configure the custom command gateway factory, enabling injection of the gateway where needed :

In the main program, I can quite happily cause the aggregate to be created, but the command gateway does not return it :

public class Main {

MyAggregate myAggregate = myCommandGateway.createMyAggregate(new CreateMyAggregateCommand(new AggregateId()));
// myAggregate is always null
}

Can anyone point out where I may be going wrong? I struggled to find any examples that use custom command gateways.

Thanks,
Steffan

Hi Steffan,

the reason you’re getting a null response is because the @CommandHandler on a constructor always has a null return value for the command. Currently, the only way to get another return value is by using a “normal” command handler class.

In CQRS, it is considered bad practice to expose your Aggregate to the senders of commands. The only way to interact with an aggregate is by sending it commands. If you would return it, you suddenly have other options. Even when you use your command model for querying, I’d suggest not to do this. Instead, create a (Query) Repository that returns the (same) aggregate.

Kind regards,

Allard Buijze