Response

Hi everyone,

I’m started with axon in this week and I need know how I can return my saved entity in my Response. I have this code:

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public CompletableFuture<SponsorRequest> create(@Valid @RequestBody SponsorRequest sponsorRequest) {
    return commandGateway.send(SponsorCreateCommand.builder()
            .id(UUID.randomUUID().toString())
            .name(sponsorRequest.getName())
            .governmentId(sponsorRequest.getGovernmentId())
            .companyName(sponsorRequest.getCompanyName())
            .fantasyName(sponsorRequest.getFantasyName())
            .foundationDate(sponsorRequest.getFoundationDate())
            .functionariesQuantity(sponsorRequest.getFunctionariesQuantity())
            .socialCapitalValue(sponsorRequest.getSocialCapitalValue())
            .socialCapitalLastUpdate(sponsorRequest.getSocialCapitalLastUpdate())
            .optionsQuantity(sponsorRequest.getOptionsQuantity())
            .netWorth(sponsorRequest.getNetWorth())
            .phone(sponsorRequest.getPhone())
            .address(sponsorRequest.getAddress())
            .addressNumber(sponsorRequest.getAddressNumber())
            .addressComplement(sponsorRequest.getAddressComplement())
            .neighborhood(sponsorRequest.getNeighborhood())
            .city(sponsorRequest.getCity())
            .state(sponsorRequest.getState())
            .country(sponsorRequest.getCountry())
            .zipCode(sponsorRequest.getZipCode())
            .activityCode(sponsorRequest.getActivityCode())
            .myMonkey(false)
            .status(SponsorStatusEnum.APPROVAL)
            .build()
    );
}

But this response only the uuid of my aggregate. Thx.

Hi Felipe,

you can, but it’s considered bad practice to do so. Your aggregate is designed to show certain behavior. By exposing it (either as a response or as a query result), you will also mix in the concern of exposing state. This pollutes the model and tends to make it more complex than necessary.

By default, Axon returns the ID of an aggregate as a result of the creation command. You can change this behavior, but that means you’ll have to wire the command handling component for the aggregate (AggregateAnnotationCommandHandler) yourself. By subclassing AggregateAnnotationCommandHandler, you can override the “resolveReturnValue” method and change the result returned. As you see, it’s possible, but clearly not designed to do this, for the aforementioned reason.

Hope this clarifies it.
Cheers,

Allard

Hi Allard, but I think is a best approach in a RestFul API return de saved object, you know another way to return the full saved entity without change the concept of the framework?

Hi Felipe,

I think we have different opinions on this. I think in general it’s a bad practice to return state on a command, and that’s especially the fact in CQRS. In CQRS, there is no such thing as “state after a command”. You have different query models that are effectively different representations of the state of the system. Depending on what the client needs, they should query one of these models. The Command Model should not be designed to expose its state, and should just contain the state required to process incoming commands.

Udi Dahan, for one, has published some articles on his blog stating that Commands shouldn’t even have any return value at all. While I don’t agree with that completely, he does make some valid arguments against return values.

Cheers,

Allard

The implementation details of the entity, I think, should remain opaque to the client, but depending on what the API is for, it’s perfectly reasonable to return a well-defined response (whose format is defined independently of the implementation and stays the same even if you refactor the underlying aggregates/sagas).

In general I think Axon is better suited to asynchronous APIs than to synchronous ones, and in our application we try to expose asynchronous APIs to clients. But in cases where we’ve needed to return a synchronous response, we’ve taken one of two approaches:

  1. Poll the query model until it indicates the operation is complete or has failed, then use the contents of the query model to compose the response.

  2. Have an event handler that request handlers can register themselves with to be notified when an event indicating the end of an operation has been published. More efficient than polling the query model, but need to be careful about which events are handled on which hosts in a clustered setup.

If you’re willing to give up asynchronous event and command delivery, and there are no asynchronous operations anywhere in your processing pipeline, option 1 doesn’t require repeated polling since the operation will be finished when the command gateway call returns. But asynchronous delivery is one of Axon’s strong points and is one of the keys to making Axon applications scale well, so I’d be wary of designing an application that requires everything to be synchronous.

-Steve

Hi Felipe,

Adding to what Allard said already, another good way to handle this particular situation would be to respond with a URI in the Location HTTP header pointing to the (future) resource in the query side. In your case, you are generating the ID right there in the controller, so it should be easy to just build an URL using Spring HATEOAS or something similar and then send it back with the response.

For a working example of that take a look at this example => https://github.com/vvgomes/event-driven-restaurant

Thanks,
-v

Hi all,

Thanks for all the reply, I think first I need decide what is async and what is sync and after I try implement something, I’ll read all the articles and the examples and then I’ll wirte a POC and share with you to receive the feedback. Thanks a lot guys :slight_smile: