Somehow I keep feeling like a total noob here - oh I am
I have my event sourced aggregate, not going to do snapshots (JPA) for now (tried, but failed, so let’s stick to one principle first), and I need a rest service to return the complete aggregate given a certain id. I was in doubt if I needed to write a repository from scratch, but from the documentation and googling I gather there should be a default implementation. And indeed injecting “org.axonframework.modelling.command.Repository” into the rest service was successful.
However, the injected repo has a “load(String)” method. But the aggregate has a localdate as the identifier, not a string. And even if I convert the date to a string, the result of the load method is an Aggregate, not a RosterDate, and no method to get the actual aggregate. Also no “all()” or any query method.
Is it weird to expect, after the initial command and event chapter in the reference guide, an example with a repository? Or should I reconstruct the aggregate in one of the projections? Seems like a blatant violation of DRY.
I would invert the question to you and ask why you need the Aggregate?
It’s not common at all to use the Aggregate for anything other than business rules!
The Aggregate shouldn’t contain any data other than the ones used for your rules (usually validations and business cases) and should not be used as a ‘query result’.
Maybe explaining your use case would help us to guide you better! =)
Ok. Good. That is where I want to go with my question.
In my understanding of DDD an aggregrate is the entry point for a logical set of domain data, which can only be manipulated through the aggregate. In this case the aggregate is a rostable date, including all the shifts that can be rostered on that date. I’m undecided yet if it should also include the actual allocation of people on the shifts. So shifts do not have a repository of their own, but are always managed through the rostable date.
So following that logic, if do a GET of 2022-0319, I’d expect a JSON/XML structure of the whole aggregate.
After having slept on it; a CRUD application may be a bad type to use as a trial for testing out CQRS (but is a natural choice). From an architectural standpoint it makes sense that in a CRUD one has a command model and query model that virtually are identical.
Yes, but it feels unnatural to construct an aggregate in the command model that is identical to the projection one. But I guess that is what you get when doing the CRUD part of an application.
Yes, but it feels unnatural to construct an aggregate in the command model that is identical to the projection one
When you phrase it like that then it may seem unnatural. But actually what you are doing is creating a projection to maintain a view of your model. The view should answer a specific question. If that question is: what is the latest state of the aggregate - then so be it. I think it is a good way of doing things because you can create as many views as you need (supposing you have different questions).