Communication between two aggregates in Axon Framework - spring-boot

I'm new to Axon Framework, CQRS and DDD. I was taught to create simple CRUD applications using relational databases. Hence, I am first focused on building the data model, not the domain model.
I would like to change my approach to software to a more pragmatic and create real-world apps. Therefore, I want to use the CQRS pattern and Event Sourcing.
I'm working on a library app right now using Spring Boot and Axon Framework. One of the basic requirements is that the user has borrowed the book. I have two Aggregates for User and Book.
This is my BookAggregate:
#Data
#AllArgsConstructor #NoArgsConstructor
#Aggregate
public class BookAggregate {
#AggregateIdentifier
private UUID id;
private String name;
private String isbnNumber;
private int amountOfCopies;
private Author author;
private Genre genre;
private PublishingHouse publishingHouse;
...
And this is my UserAggregate:
#Data
#AllArgsConstructor #NoArgsConstructor
#Aggregate
public class UserAggregate {
#AggregateIdentifier
private UUID id;
private String firstName;
private String lastName;
private String email;
private String password;
private String confirmPassword;
private Set<Role> roles;
private Date birthDate;
private String telNumber;
private Address address;
...
My question is: should I create an intermediary aggregate between these two aggregates something like SQL JOIN? In this one example, I'd like to see how similar use cases where two aggregates communicate with each other are implemented in Axon Framework.

should I create an intermediary aggregate between these two aggregates
something like SQL JOIN? In this one example, I'd like to see how
similar use cases where two aggregates communicate with each other are
implemented in Axon Framework.
Great question. I'm going to start by saying no, and then try to help you understand why.
Let's start with why aggregates exist. From the DDD reference:
Aggregates
It is difficult to guarantee the consistency of changes to objects in a model with complex associations.
[...]
Therefore:
Cluster the entities and value objects into aggregates and define boundaries around each. Choose one entity to be the root of each aggregate, and allow external objects to hold references to the root only
OK, so the reason for using aggregates is to avoid intermediaries.
Since you are doing CQRS (which implies DDD and event sourcing), you have a command side and a query side (Command Query Request Segregation). If you are more familiar with CRUD style applications and relational databases, chances are that you're focusing on the query side and not the command side.
Let's clarify a few things, in CQRS:
Aggregates are only relevant to the command side
Aggregates are responsible for handling commands and publishing events
Aggregates are responsible for enforcing business rules
What this means is that for the command side:
Commands are passed to aggregates, which decide if they should publish events or deny the command.
On the query side:
Events originating from the command side are processed to build up a query model (probably what you refer to as the data model)
Hence, I am first focused on building the data model, not the domain
model
In an event sourced system, you typically focus on the domain model and the associated events. The query model can be fully built based on the events from the domain model.
Since you are not yet focusing on the domain model you don't yet have to care about aggregates :)
Again, back to your original question:
One of the basic requirements is that the user has borrowed the book
should I create an intermediary aggregate between these two aggregates
something like SQL JOIN?
Based on your domain, you already have a User and Book aggregate. You have single requirement that users can borrow books. Now I'm no expert on your domain, but ask yourself: why do you need another aggregate? What would this new aggregate be responsible for? What would be wrong with just having Book.borrow(userId) which publishes a BookBorrowed(bookId, userId) event if the user is allowed to borrow the book?

I very, very much like the suggestions given by #martingreber earlier. Please take those into account, as those are about the conceptual necessity of your current set-up.
From a pragmatic approach, there are also a couple of things I'd like to add (although I wouldn't anticipate these to form the answer completely).
Firstly, your BookAggregate and UserAggregate contain quite some state. When doing CQRS, I would recommend that your command model (read: the aggregates) only contain state necessary for task execution. What I mean with that, is that the sole fields required to reside inside the BookAggregate and UserAggregate are those you use to perform validations with inside your #CommandHandler annotated methods. The rest can all go, as it is no being used. Furthermore, if it turns out to be required at a later stage, you can simply add another event sourcing handler later. That's the beauty of event sourcing really; you can add state from events which are already present in the aggregate's event stream whenever you really start needing it.
Secondly, towards the inter-aggregate communication. It is good to note, as was also pointed out by Martin, that Aggregates typically are the Command Model. As such, they only handle Commands and publish Events. The #EventSourcingHandler annotated methods might suggest you can handle any event, but in reality, the Aggregate will only handle the events it itself has published. This holds as it is those events which you would need to recreate the state of the aggregate.
Now, it is the events which will allow for the inter-aggregate communication you require. As the aggregates just work with their own concepts and state, you will have to introduce another component which reacts to the published events to dispatch commands to other aggregates. This component can simply be a regular Event Handling Component (read: a class with #EventHandler annotated functions in it). If the process you want to react to has a notion of times, requires state to perform its task and communicates with N aggregates? Then you could use a Saga for example.
Thirdly, and arguable most important, is to decide whether you really need to have two distinct aggregates in your system. It is this why I applaud #martingerber his answer.
Nonetheless, these are my two cents. Hope it helps you out.

Related

Will Spring Data's save() method update an entity in the database if there are no changes in the entity?

When editing a form, the user may sometimes not change the form and still click the submit button. In one of the controller methods below, will the save() method perform a query to the database and update the fields even if the user didn't change anything?
PostMapping("/edit_entry/{entryId}")
public String update_entry(
#PathVariable("entryId") Long entryId,
#RequestParam String title,
#RequestParam String text
) {
Entry entry = this.entryRepo.findById(entryId).get();
if (!entry.getTitle().equals(title))
entry.setTitle(title);
if (!entry.getText().equals(text))
entry.setText(text);
this.entryRepo.save(entry);
return "redirect:/entries";
}
And also, are the "if" statements necessary in this case?
What exactly happens during a call to save(…) depends on the underling persistence technology. Fundamentally there a re two categories of implementations:
Implementations that actively manage entities. Examples of this are JPA and Neo4j. Those implementations keep track of the entities returned from the store and thus are able to detect changes in the first place. You pay for this with additional complexity as the entities are usually instrumented in some way and the change detection of course also takes time even if it ends up not detecting any changes. On the upside though the only trigger updates if needed.
Implementations that do not actively manage entities. Examples are JDBC and MongoDB. Those implementations do not keep track of entities loaded from the data store and thus do not instrument them. That also means that there is no way of detecting changes as all the implementation sees is an entity instance without any further context.
In your concrete example, a MongoDB implementation would still issue an update while JPA will not issue an update at all if the request params do not contain differing values.

One to One relationship with axon framework

I'm new to Axon Framework. I've a requirement within an asset management module which I am working on.
In this module different types of asset are build, which need to be paired in a similar fashion as one to one relationships in SQL. I am finding it difficult to design an Aggregate for this format.
The business logic validation is as follows:
Two assetIds are inputs. These identifiers resemble aggregate identifiers.
Then, load the asset instances tied to these assetIds and check if the status is unpaired or paired. If both the assets are unpaired then pair them (update the status to paired and add UUID to associatedAssets). Else raise an exception.
I have come up with the following Aggregate class:
#Aggregate
#Data
public class AssetAggregate {
#AggregateIdentifier
private UUID assetId;
private String assetType;
private HashMap<String,String> attributes;
private String status;
private String modifier;
private UUID associatedAsset;
}
My Command Message for pairing is this:
#Data
public class PairAssetCommand {
private UUID assetAId;
private UUID assetBId;
}
In the sample you have given, the PairAssetsCommand can not be handled by a single AssetAggregate as it spans the consistency boundary of two distinct aggregate instances. Namely, two different AssetAggregates.
Note that the Aggregate defines the consistency boundary within your command model. Thus any command taken in by it and all it's resulting events (and following state changes) will be regarded as an atomic operation. Making associations between several entities through this can mean two things:
You create a bigger Aggregate class which spans all AssetAggregates.
You have a External Command Handler (i.e. a #CommandHandler outside of an Aggregate) which handles the PairAssetsCommand.
I'd advise against option one, as it will enlarge the consistency boundary towards the entire set of assets in your system. This will eventually become a major bottleneck the maintain an Aggregate's requirement of "keeping the consistency boundary".
That thus leaves option 2. Let's rephrase the business logic you have defined:
if both the assets are unpaired then pair them(update the status to paired and add UUID to associatedAssets) else raise an exception
This means you cannot validate on a single instance, but need to do this on several. Again, you can take two routes to solving this:
Dispatch a AssociateWithAssetCommand to both the AssetAggregates and dispatch a compensating command if one of the AssetAggregates is already associated.
Use set based validation in the external command handler handling the PairAssetsCommand to validate your business logic.
Which of the two is best is left to preference I'd say. Solution two requires you to have a small query model containing a set of assets and their association status'. Added, this query model needs to be updated in the same transaction as when the association commands occur. Thus, somewhat more complicated.
Hence solution one would be the simplest way to go in your scenario.

DDD / Presenter pattern VS Use case optimal query

In this great book about Domain-Driven Design, a chapter is dedicated to the user interface and its relationship to domain objects.
One point that confuses me is the comparison between Use case optimal queries and presenters.
The excerpt dealing with optimal queries (page 517) is:
Rather than reading multiple whole Aggregate instances of various
types and then programmatically composing them into a single container
(DTO or DPO), you might instead use what is called a use case optimal
query.
This is where you design your Repository with finder query
methods that compose a custom object as a superset of one or more
Aggregate instances.
The query dynamically places the results into a
Value Object (6) specifically designed to address the needs of the use
case.
You design a Value Object, not a DTO, because the query is
domain specific, not application specific (as are DTOs). The custom
use case optimal Value Object is then consumed directly by the view
renderer.
Thus, the benefit of optimal queries is to directly provide a specific-to-view value object, acting as the real view model.
A page later, presenter pattern is described:
The presentation model acts as an Adapter. It masks the details of the
domain model by providing properties and behaviours that are designed
in terms of the needs of the view.
Rather than requiring the
domain model to specifically support the necessary view properties, it
is the responsibility of the Presentation Model to derive the
view-specific indicators and properties from the state of the domain
model.
It sounds that both ways achieve the construction of a view model, specific to the use case.
Currently my call chain (using Play Framework) looks like:
For queries: Controllers (acting as Rest interface sending Json) -> Queries (returning specific value object through optimal queries)
For commands: Controllers (acting as Rest interface sending Json) -> Application services (Commands) -> domain services/repositories/Aggregates (application services returns void)
My question is: if I already practice the use case optimal query, what would be the benefit of implementing the presenter pattern? Why bother with a presenter if one could always use optimal queries to satisfy the client needs directly?
I just think of one benefit of the presenter pattern: dealing with commands, not queries, thus providing to command some domain objects corresponding to the view models determined by the presenter. Controller would then be decoupled from domain object.
Indeed, another excerpt of Presenter description is:
Additionally, edits performed by the user are tracked by the
Presentation Model.
This is not the case of placing overloaded
responsibilities on the Presentation Model, since it's meant to adapt
in both directions, model to view and view to model.
However, I prefer sending pure primitives to application services (commands), rather than dealing directly with domain object, so this benefit would not apply for me.
Any explanation?
Just a guess :)
The preseneter pattern could reuse your repository's aggregate finder methods as much as possible. For example, we have two views, in this case we need two adapters(an adapter per view), but we only need one repository find method:
class CommentBriefViewAdapter {
private Comment comment;
public String getTitle() {
return partOf(comment.getTitle());
//return first 10 characters of the title, hide the rest
}
.....//other fields to display
}
class CommentDetailViewAdapter {
private Comment comment;
public String getTitle() {
return comment.getTitle();//return full title
}
.....//other fields to display
}
//In controller:
model.addAttribute(new CommentBriefViewAdapter(commentRepo.findBy(commentId)));
// same repo method
model.addAttribute(new CommentDetailViewAdapter(commentRepo.findBy(commentId)));
But optimal queries is view oriented(a query per view). I think these two solutions are designed for none-cqrs style ddd architecture. They're no longer needed in a cqrs-style arichitecture since queries are not based on repository but specific thin data layer.

Validation on domain entities along with MVP

How do you apply validation in an MVP/domain environment ?
Let me clearify with an example:
Domain entity:
class Customer
{
string Name;
etc.
}
MVP-model
class CustomerModel
{
string Name;
etc.
}
I want to apply validation on my domain entities but the MVP model has it's own model/class
apart from the domain entity, does that mean I have to copy the validation code
to also work on the MVP-model?
One solution I came up with is to drop the MVP-model and use the domain entity as MVP-Model,
but I don't want to set data to the entities that isn't validated yet.
And second problem that rises is that if the entity has notify-events,
other parts of the application will be affected with faulty data.
A third thing with that approach is if the user edits some data and then cancels the edit, how do I revert to the old values ? (The entity might not come from a DB so reloading the entity is't possible in all cases).
Another solution is to make some sort of copy/clone of the entity in question and use the copy as MVP-model, but then it might get troublesome if the entity has a large object graph.
Anyone has some tips about these problems?
Constraining something like the name of a person probably does not rightfully belong in the domain model, unless in the client's company there is actually a rule that they don't do business with customers whose names exceed 96 characters.
String length and the like are not concerns of the domain -- two different applications employing the same model could have different requirements, depending on the UI, persistence constraints, and use cases.
On the one hand, you want to be sure that your model of a person is complete and accurate, but consider the "real world" person you are modeling. There are no rules about length and no logical corollary to "oops, there was a problem trying to give this person a name." A person just has a name, so I'd argue that it is the responsibility of the presenter to validate what the user enters before populating the domain model, because the format of the data is a concern of the application moreso than the domain.
Furthermore, as Udi Dahan explains in his article, Employing the Domain Model Pattern, we use the domain model pattern to encapsulate rules that are subject to change. That a person should not a have a null name is not a requirement that is likely ever to change.
I might consider using Debug.Assert() in the domain entity just for an added layer of protection through integration and/or manual testing, if I was really concerned about a null name sneaking in, but something like length, again, doesn't belong there.
Don't use your domain entities directly -- keep that presentation layer; you're going to need it. You laid out three very real problems with using entities directly (I think Udi Dahan's article touches on this as well).
Your domain model should not acquiesce to the needs of the application, and soon enough your UI is going to need an event or collection filter that you're just going to have to stick into that entity. Let the presentation layer serve as the adapter instead and each layer will be able to maintain its integrity.
Let me be clear that the domain model does not have to be devoid of validation, but the validation that it contains should be domain-specific. For example, when attempting to give someone a pay raise, there may be a requirement that no raise can be awarded within 6 months of the last one so you'd need to validate the effective date of the raise. This is a business rule, is subject to change, and absolutely belongs in the domain model.

What is a Data Transfer Object (DTO)?

What is a Data Transfer Object?
In MVC are the model classes DTO, and if not what are the differences and do we need both?
A Data Transfer Object is an object that is used to encapsulate data, and send it from one subsystem of an application to another.
DTOs are most commonly used by the Services layer in an N-Tier application to transfer data between itself and the UI layer. The main benefit here is that it reduces the amount of data that needs to be sent across the wire in distributed applications. They also make great models in the MVC pattern.
Another use for DTOs can be to encapsulate parameters for method calls. This can be useful if a method takes more than four or five parameters.
When using the DTO pattern, you would also make use of DTO assemblers. The assemblers are used to create DTOs from Domain Objects, and vice versa.
The conversion from Domain Object to DTO and back again can be a costly process. If you're not creating a distributed application, you probably won't see any great benefits from the pattern, as Martin Fowler explains here.
The definition for DTO can be found on Martin Fowler's site. DTOs are used to transfer parameters to methods and as return types. A lot of people use those in the UI, but others inflate domain objects from them.
A DTO is a dumb object - it just holds properties and has getters and setters, but no other logic of any significance (other than maybe a compare() or equals() implementation).
Typically model classes in MVC (assuming .net MVC here) are DTOs, or collections/aggregates of DTOs
In general Value Objects should be Immutable. Like Integer or String objects in Java. We can use them for transferring data between software layers. If the software layers or services running in different remote nodes like in a microservices environment or in a legacy Java Enterprise App. We must make almost exact copies of two classes. This is the where we met DTOs.
|-----------| |--------------|
| SERVICE 1 |--> Credentials DTO >--------> Credentials DTO >-- | AUTH SERVICE |
|-----------| |--------------|
In legacy Java Enterprise Systems DTOs can have various EJB stuff in it.
I do not know this is a best practice or not but I personally use Value Objects in my Spring MVC/Boot Projects like this:
|------------| |------------------| |------------|
-> Form | | -> Form | | -> Entity | |
| Controller | | Service / Facade | | Repository |
<- View | | <- View | | <- Entity / Projection View | |
|------------| |------------------| |------------|
Controller layer doesn't know what are the entities are. It communicates with Form and View Value Objects. Form Objects has JSR 303 Validation annotations (for instance #NotNull) and View Value Objects have Jackson Annotations for custom serialization. (for instance #JsonIgnore)
Service layer communicates with repository layer via using Entity Objects. Entity objects have JPA/Hibernate/Spring Data annotations on it. Every layer communicates with only the lower layer. The inter-layer communication is prohibited because of circular/cyclic dependency.
User Service ----> XX CANNOT CALL XX ----> Order Service
Some ORM Frameworks have the ability of projection via using additional interfaces or classes. So repositories can return View objects directly. There for you do not need an additional transformation.
For instance this is our User entity:
#Entity
public final class User {
private String id;
private String firstname;
private String lastname;
private String phone;
private String fax;
private String address;
// Accessors ...
}
But you should return a Paginated list of users that just include id, firstname, lastname. Then you can create a View Value Object for ORM projection.
public final class UserListItemView {
private String id;
private String firstname;
private String lastname;
// Accessors ...
}
You can easily get the paginated result from repository layer. Thanks to spring you can also use just interfaces for projections.
List<UserListItemView> find(Pageable pageable);
Don't worry for other conversion operations BeanUtils.copy method works just fine.
To me the best answer to the question what is a DTO is that DTO's are simple objects that should not contain any business logic or methods implementation that would require testing.
Normally your model (using the MVC pattern) are intelligent models, and they can contain a lot of/some methods that do some different operations for that model specifically (not business logic, this should be at the controllers). However, when you transfer data (eg. calling a REST (GET/POST/whatever) endpoint from somewhere, or consuming a webservice using SOA, etc...) you do not want to transmit the big sized object with code that is not necessary for the endpoint, will consume data, and slow down the transfer.
With MVC data transfer objects are often used to map domain models to simpler objects that will ultimately get displayed by the view.
From Wikipedia:
Data transfer object (DTO), formerly known as value objects or VO, is
a design pattern used to transfer data between software application
subsystems. DTOs are often used in conjunction with data access
objects to retrieve data from a database.
All credits goes to Rick-Andreson
Production apps typically limit the data that's input and returned using a subset of the model. There are multiple reasons behind this and security is a major one. The subset of a model is usually referred to as a Data Transfer Object (DTO), input model, or view model.
A DTO may be used to:
Prevent over-posting.
Hide properties that clients are not supposed to view.
Omit some properties in order to reduce payload size.
Flatten object graphs that contain nested objects.
Flattened object graphs can be more convenient for clients.
Practical implementation of a DTO approach, by Rick-Andreson on Microsoft Web APIs best tutorials and practices using C# and ASP .Net Core 5:
The principle behind Data Transfer Object is to create new Data Objects that only include the necessary properties you need for a specific data transaction.
Benefits include:
Make data transfer more secure
Reduce transfer size if you remove all unnecessary data.
Read More: https://www.codenerd.co.za/what-is-data-transfer-objects
Some programmers use DTO to distinguish their final object data that is going to be passed through an API. So, it is basically a payload object to an endpoint. Like, you could name your contact form values object that you pass to the server as contactFormDto or contactFromPayload, then you or any other programmer know what you have in that object is final shape of the data, that is going to travel through network.
I would explain DTO to my kid as
My son, Data Transfer Object (aka DTO) **is used to encapsulate data we send from one endpoint to another.
Use DTO to define interfaces for input and output for endpoints in your system
In this context think of a system as a collection of endpoints. And endpoints can be anything between (mobile app, web app, backend API) that talk with each other.
Data transfer object (DTO) describes “an object that carries data
between processes” (Wikipedia) or an “object that is used to encapsulate data,
and send it from one subsystem of an application to another” (Stack Overflow
answer).
DefN
A DTO is a hardcoded data model. It only solves the problem of modeling a data record handled by a hardcoded production process, where all fields are known at compile-time and therefore accessed via strongly typed properties.
In contrast, a dynamic model or "property bag" solves the problem of modeling a data record when the production process is created at runtime.
The Cvar
A DTO can be modeled with fields or properties, but someone invented a very useful data container called the Cvar. It is a reference to a value. When a DTO is modeled with what I call reference properties, modules can be configured to share heap memory and thereby collaboratively work on it. This completely eliminates parameter passing and O2O communication from your code. In other words, DTOs having reference properties allow code to achieve zero coupling.
class Cvar { ... }
class Cvar<T> : Cvar
{
public T Value { get; set; }
}
class MyDTO
{
public Cvar<int> X { get; set; }
public Cvar<int> Y { get; set; }
public Cvar<string> mutableString { get; set; } // >;)
}
Source: http://www.powersemantics.com/
Dynamic DTOs are a necessary component for dynamic software. To instantiate a dynamic process, one compiler step is to bind each machine in the script to the reference properties the script defines. A dynamic DTO is built by adding the Cvars to a collection.
// a dynamic DTO
class CvarRegistry : Dictionary<string, Cvar> { }
Contentions
Note: because Wix labeled the use of DTOs for organizing parameters as an "anti-pattern", I will give an authoritative opinion.
return View(model); // MVC disagrees
My collaborative architecture replaces design patterns. Refer to my web articles.
Parameters provide immediate control of a stack frame machine. If you use continuous control and therefore do not need immediate control, your modules do not need parameters. My architecture has none. In-process configuration of machines (methods) adds complexity but also value (performance) when the parameters are value types. However, reference type parameters make the consumer cause cache misses to get the values off the heap anyway -- therefore, just configure the consumer with reference properties. Fact from mechanical engineering: reliance on parameters is a kind of preoptimization, because processing (making components) itself is waste. Refer to my W article for more information. http://www.powersemantics.com/w.html.
Fowler and company might realize the benefits of DTOs outside of distributed architecture if they had ever known any other architecture. Programmers only know distributed systems. Integrated collaborative systems (aka production aka manufacturing) are something I had to claim as my own architecture, because I am the first to write code this way.
Some consider the DTO an anemic domain model, meaning it lacks functionality, but this assumes an object must own the data it interacts with. This conceptual model then forces you to deliver the data between objects, which is the model for distributed processing. However on a manufacturing line, each step can access the end product and change it without owning or controlling it. That's the difference between distributed and integrated processing. Manufacturing separates the product from operations and logistics.
There's nothing inherently wrong with modeling processing as a bunch of useless office workers who e-mail work to one another without keeping an e-mail trail, except for all the extra work and headache it creates in handling logistics and return problems. A properly modeled distributed process attaches a document (active routing) to the product describing what operations it came from and will go to. The active routing is a copy of the process source routing, which is written before the process begins. In the event of a defect or other emergency change, the active routing is modified to include the operation steps it will be sent to. This then accounts for all the labor which went into production.

Resources