I'll be starting on a greenfield project in a few months.
The project will contain lot's of business logic, spread over several subdomains
. Yes, we'll be using principles of Domain Driven Design
.
Tech will consist of Spring, Spring Boot & Hibernate
stack.
I was looking after some Java libs to cover infrastructural things like:
domain event publication
event store
event deduplication
resequencers
on consumer sideprojections
reliable publishing
reliable delivery & redelivery
- ...
I came across the Axon Framework
. I already heard about it, didn't know it in details. So I read some blogposts, little bit of documentation and watched some broadcasts on Youtube.
It seems very promising, I'm considering to use it because I don't want to reinvent to wheel over and over again on the infrastructural side.
So I'm looking for someone to answer and clarify my questions:
Command handling
Axon use CommandHandlers
with void
methods. Is it possible to make them return a value (for instance a generated business id) or objects for notification purposes concerning the business operation?
It's not a issue to me that the method will be I/O blocking by this.
Local vs remote domain events publication
I want to have a clear separation of local
vs remote
domain events.
Local domain
events should only be visible and consumed to the local subdomain. Is it possible to configure event consumption sync and/or async?
My Local domain events can be 'fat'. They are allowed to carry more data because it won't cross the domain boundaries.
Remote domain events
will be 'thin', so only the minimum data necessary for remote domains. This type op events need always to be handles async.
Is it possible to convert a local (fat) domain event to a remote (thin) domain event at the edge of a domain? By 'edge', I mean the infrastructural side. By this, the domain model doesn't need to know distinction between local & remote domain events.
CQRS synchronously
My application will consist of 1 (maybe 2) core domains
and several subdomains
. Some domains contain lot's of business logic and will require CQRS
.
Other domain will be more 'crudy' style.
Is it possible to do CQRS
synchronously?
I want to start this way before adding technical complexities like async handling. It this plossible with Axon
?
This also means that domain events will be stored in a events store without using event sourcing
.
Can Axon's event store
be used without event sourcing?
Same for projection stuff, I just want to projection domain events to build my read model.
Modular monolith
We'll use a modular monolith
.
Not very trendy these days with all the microservices
stuff. Although, I'm convinced of having a monolith where each domain is completely separated (application code & DB-schema), where operations will be handled with eventual consistency and domain events contain the necessary data.
Later on, and if necessary, it will be easier to migrate to a microservices architecture
.
Is Axon a framework that fits in a modular monolith kind of architecture? Is there anything to take into account?
Fully separated domain model (persistence agnostic)
The domain model will be completely separated from the data model.
We need to have a repository that reads a data model (using Hibernate
) and uses a data mapper
to create an aggregate when it needs to be loaded.
The other way is also needed, an aggregate needs to be converted and saved into the data model (using data mapper).
Additionally, the aggregates's domain events need to be stored into an event store and published to local or remote event handlers.
This has some consequences:
we need to have full control of repository implementation that communicates with one or more DAO's (Spring data repositories) to take the necessary data out of Hibernate entities and construct an aggregate with it. An aggregate might be modeled in 2 or even 3 relational tables after all.
we don't need any Hibernate annotation in the domain model
Is this approach possible with Axon? I only see examples using direct JPA (domain model maps 1 to 1 to entities) or event sourcing.
This approach is really a deal breaker for us, a separated domain model gives so much more possibilities than mapping it directly to data entities.
Below an example of what I want to achieve:
Aggregate (without JPA) in some domain model package:
public class ScoringResultAggregate {
// members, constructor, operation omitted for brevity
}
Hibernate Entity in some infrastructure package:
@Entity
@Table(name ="SOME_TABLE_NAME)
public class ScoringResultEntity {
// member and getters & setters; no domain logic
}
Repository interface that belongs to the domain model:
public interface ScoringResultRepository {
void save(ScoringResultAggregate scoringResultAggregate);
ScoringResultAggregate findByApplicationNumber(ApplicationNumber applicationNumber);
}
Adapter that implements repository interface; responsible for mapping aggregate from/to data (JPA) model:
class ScoringResultAdapterRepository implements ScoringResultRepository {
private ScoringResultJpaRepository scoringResultJpaRepository;
ScoringResultJPARepository(ScoringResultJpaRepository scoringResultJpaRepository) {
this.scoringResultJpaRepository= scoringResultJpaRepository;
public void save(ScoringResultAggregate scoringResultAggregate) {
// converts aggregate to ScoringResultEntity and saves the state into DB
}
public ScoringResultAggregate findByApplicationNumber(ApplicationNumber applicationNumber) {
// loads an ScoringResultEntity from DB and converts it into an aggregate
}
}
Axon Server
Axon server
looks very promising. Although, is it only useful for event sourcing
?
Can it be used together with a Sql DB where aggregates are stored (state persistence) and domain events get persisted in Axon Server?
Lot of questions. Hopefully, someone with Axon experience can help me out :-)