Reputation: 5286
I am working with DDD
and Spring
using MongoDB
.
Now the since MongoDB
is a DocumentDB
and no schema validations are present, The AggregateRoot
and the Document class that gets stored in the MongoDB are two different classes and the Repository
translates content between those two classes while reading and writing data to database
.
Since the Root entity class is different from the class being stored to DB, Spring doesn't trigger the DomainEvents
of the AggregateRoot
.
Is there a way I can get trigger the events of the Root entity from the Repository after storing the data to the database? (maybe by an explicit invoke)
Since the MongoDB and Aggregates are a 1:1 fit. So does that mean that we generally shouldn't make a two different classes one as AggregateRoot
and another the Document Class for storing aggregate roots in mongoDB? Wouldn't we have to add @Document annotation on top of our Aggregate which would leak infrastructure code in our Domain Model?
Upvotes: 3
Views: 1785
Reputation: 5286
After a while I figured out the solution, from the upvotes I believe others are facing the same problem, here is the solution:
Answer: Yes, we can. In SpringBoot
we can use/Autowire
the ApplicationEventPublisher
interface and then call publishEvent(event)
method.
If you're making a separate class for Db collection and Aggregate you would need to expose out your DomainEvents
and a method for ClearingDomainEvents
in your aggregate since the AbstractAggregateRoot<T>
has these methods as protected
. Below is an example of raising an event on creation:
public class MyAggregateRootClass extends AbstractAggregateRoot<MyAggregateRootClass>
{
public MyAggregateRootClass(String property1, String property2) {
// set the fields here
registerEvent(new MyAggregateRootCreated(someArgs));
}
public Collection<Object> getDomainEvents() {
return super.domainEvents();
}
public void clearDomainEvents() {
super.clearDomainEvents();
}
}
The Repository Code would look like:
@Repository
@RequiredArgsConstructor // using lombok here, you can create a constructor if you want
public class MyAggregateRepository {
private final ApplicationEventPublisher eventPublisher;
private final AggregateMongoRepository repository;
public void save(MyAggregateRootClass aggToSave) {
AggregateDao convertedAgg = new AggregateDao(aggToSave);
repository.save(convertedAgg);
// raise all the domain events
for (Object event : aggToSave.getDomainEvents())
eventPublisher.publishEvent(event);
// clear them since all events have been raised
aggToSave.clearDomainEvents();
}
}
AggregateRoot
and another the Document Class for storing aggregate roots in mongoDB
?Answer: No, that does not mean that. The goal of the DDD
would be to separate infrastructure
from the Domain
and keep the Domain
agnostic of all infrastructure code. If they both are the same then below is the impact:
@Document
annotation on your Aggregate Class
would make you change your Domain
if you're switching frameworks or swapping Mongodb
with SQL
.infrastructure dependencies
, creeping in the infrastructure annotations
into the AggregateRoot
would not be the best wayIf you do want to just keep it simple and use the same class for both and not create a separate class then make sure you're sure about the below:
Entities
of the Aggregate
in a separate collection and you there is no possibility that those Entities
would ever grow into their own Aggregates
In the end it depends. Feel free to drop in comments and I'll try my best to answer all of them, quite active on stack.
Upvotes: 1