Why are we privilege the use of repositories over other possibilities to handle transactions?

Hello

I take an example for query views from https://files.gotocon.com/uploads/slides/conference_7/336/original/The-Big-Friendly-Monolith.pdf

@Component
public class AllOrdersProjection {
  @Autowired
  EntityManager entityManager;
  @EventHandler
  void handle(OrderLineAddedEvent evt) {
  /* Find Order JPA entity, add the line so it gets persisted. */
  }
  public List<OrderRecord> findAllOrders() {
    return entityManager.createQuery("select e from OrderRecord e",OrderRecord.class).getResultList();
  }
}

I don’t know if my questions fits this forum but I didn’t receive an answer on stackoverflow sadly.

My question is: what is the reason to use repositories in Spring (and Axon for Aggregates) instead of entity- or transactionmanager or the JpaProvider which should make use of both for transactions, should it?

Maybe someone can give a conceptual or even technical explanation?

Thanks!
ĂĽberSpotz

Hi @uberSpotz

can you please clarify your question? I’m not sure (I guess others feel the same way, which may explain the lack of response on SO) what you are comparing to what.

Do you mean, why have Aggregates in Axon and projections in Spring when you can have it all in Spring (without Axon)?

Or do you mean, why use Spring repositories for Axon projections when you can have the same with pure JPA?

I can try and have a stab at answering your question @uberSpotz.

The Axon Framework uses the CQRS pattern (see Command Query Responsibility Separation).

Essentially there are two models: the command model and the query model.

The command model is modeled in Axon using @Aggregates, @CommandHandlers, etc.

An @Aggregate applies an event which is then routed to its @EventSourcingHandler and to any other @Component within your system which subscribes to receiving that event (with the @EventHandler annotation like in the example code).

what is the reason to use repositories in Spring (and Axon for Aggregates) instead of entity- or transactionmanager or the JpaProvider which should make use of both for transactions, should it?

The reason is because the CQRS pattern embraces eventual consistency. You are using repositories in Spring (in the example code you gave above) for the query side of things. You embrace the fact that you will have a slight delay in the command and query model staying in sync. The AllOrdersProjection is in the query model and so does not need to take part in the OrderLineAddedEvent transaction in the command model.

If you have a business constraint - an invariant - which requires immediate consistency in your command model - then consider reading up about set based validation.

In my example app (with postgres as the store for the command and query model) I have an example of using a single DB transaction to enforce immediate consistency using command side projections (see here).

You can see it in the /set-based-validation endpoints:

1 Like

This one.

Isn’t it purely to encapsulate the specific CRUD method of one particular Aggregate or is there technically more to it? Hibernate for example can together with Hikari do pooled connections, transaction demarcation, create an entitymanager with a persistence context, flush and commit the transaction.

I haven’t read a description on the râisón d’être of repositories (eq. the repository-unitofwork pattern?). Why this one to one relation of repositories to aggregates?

Thanks Milen.

That’s what I thought your question is. Unfortunately, due to the popularity of Spring, many examples and demos use Spring repositories for projections, making it look like this is a requirement. It is not. You don’t have to use Spring repositories (or anything Spring, for that matter). You can use whichever storage you wish for your projections. It could be JPA with Hibernate or simple JDBC, or it may even be something completely different like NoSQL or LDAP or files or anything that works best for the use case.

1 Like

I’d ask myself:

  • What happens if I want to switch from JPA to JDBC or vice versa?
  • What happens if my projection shouldn’t write directly into a database but needs to call a REST Endpoint, GRPC, publish a Kafka topic….
  • What happens if the event changes?
  • What happens if I need to add further events to listen to?

If you can answer this questions with „Well, than I just need to adapt the projection class and that’s it.“ or „pretty much the same with or without a Repository“, then you can skip the Repository. If you say „I need to adapt my event handler and my REST endpoint that reads the data“, then it isn’t that obvious any more.

If the projection class becomes bigger and bigger you might want to split it up. But how? Does it have more than one reason to change? What are those? If it adapts events, manages database access,… creating a Repository to move all the writing stuff out might be the right choice.

If you then have some projections with and some without Repository, colleagues might be confused about that.

So you may end up using Repositories for the sake of consistency in your code base.

Then the question arises, why they are all the same and can be generated by a framework. So the whole story starts again.

This is software design and architecture, at least for me. I recommend reading what Eric Evans writes about a Repository and look up „Hexagonal architecture“.

1 Like

I’m stil not sure I get what your asking for. Repository is just an abstraction that’s easy to work with in Spring IMHO. But you are free to use whatever you want for your projections. We also have a mongo extension for example if you rather store your projection in Mongo.

Dear @milendyankov

in the Spring Data reference I can read “how to use repositories”.
Axon uses them EventSourcingRepository<DomainAggregate> for persisting Aggregates / Event Stores.

My issue is that I haven’t found a source yet that explains technically what you say. Why are Spring repositories special, what do they do better than

You can use whichever storage you wish for your projections. It could be JPA with Hibernate or simple JDBC, or it may even be something completely different like NoSQL or LDAP or files or anything that works best for the use case.

Why did they seem like the best choice to the creators of Axon in order to persist Aggregates / EventStores? What are Repositories technically?

So it’s an abstraction layer for database access of many kinds to begin with and in hexagonal-parlance it’s a port?

EventSourcingRepository<DomainAggregate> then is an adapter?

So it’s an abstraction layer for database access of many kinds to begin with

Yes.

and in hexagonal-parlance it’s a port?

I’d rather say that the (current) Port is the network connection to the Database, the Repository implementation is the Adapter and the Repository interface belongs to the inner core that I’d call a “Boundary” in sense of “Entity Control Boundary”. But that’s just my interpretation. I might use or understand these words different than others.

The most important thing is that you stay able to change the code and “tackle the complexity” ;-).

I find Hexagonal Architecture helpful in that manner. You can focus on business logic in the core and be able to write it to last for at least some technology changes. And on the other hand you can change the technologies you use to get the data you need. These abilities are only valuable if they are needed. If the application or service can be rewritten without great effort, the business logic is simple and there are good consumer driven integration tests, then you are most likely be better off using as few abstractions as possible.

EventSourcingRepository<DomainAggregate> then is an adapter?

In my interpretation the implementation of the EventSourcingRepository is the adapter.

1 Like

Hey, @uberSpotz, I’m currently traveling and don’t have much time to respond with many details. However, the term Repository has many meanings, which may be what causes your confusion.

Repository in Domain-Driven Design

Ideally, read the blue book where repositories are well explained. Alternatively, look at page 51 of Domain Driven Design Quickly where you’d find:

The Repository may store references to some of the objects.
When an object is created, it may be saved in the Repository,
and retrieved from there to be used later. If the client requested
an object from the Repository, and the Repository does not have
it, it may get it from the storage. Either way, the Repository acts
as a storage place for globally accessible objects.

The Axon Framework provides implementations of such Repositories. Those are used on the command side to store and load Aggregates. There are a few implementations to choose from.

Repository in Spring

According to the docs:

The goal of the Spring Data repository abstraction is to significantly reduce the amount of boilerplate code required to implement data access layers for various persistence stores.

This is fundamentally different. It’s a generic data access layer that makes using different DBs within the Spring framework easier. In that sense, it’s sort of comparable to JPA and JDO, and many other data access abstractions. When using Axon with Spring, one can use Spring Data repositories to build projections (typically on the query side). But it’s not a requirement. One can use JPA, JDBC, or anything else.

2 Likes