Make sure projection happens in saga

so i have use case that i need to create a client and with client creation will create some default Tarrif , so i go with using Saga, but the issue now how to make sure that the client projection is done before projecting the tarrifs ?

Hi @skady and welcome!

Why do you need a projection (I assume this is a JPA entity/repository)? Your saga should listen on an event and should not be dependent on any projection. Basically, the event should contain enough information to allow creating a default Tarif. A projection is just a projection of information contained in the same event. Unless you do some custom computation in that projection which you want to use when creating a tarif.

Could you share a bit more about your events?

David

Hi @BribedSeeker904,

thank you for your reply. my saga listens to the ClientCreatedEvent and then fires TarrifCreateCommand and for that everything works fine. the problem comes at the eventHandler for the TarrifCreatedEvent as it tries to persist the Tarrif and there is @ManyToOne with Client , so it does not find the client so it fails

I thought that this would be exactly the problem. You have two aggregates, a Client and a Tarrif. One of DDD principles is, that aggregates reference each other only thru an identifier. However, you are trying to reference a Client from a Tarrif as entity (hence @ManyToOne). This defeats the purpose of separate aggregates (in Axon and DDD terms) if you combine them at JPA model.

You could try to use an identifier instead of a class:

// Instread of this

@Entity
class TarifEntity {
   @Id
   private int id;

  @ManyToOne
   private ClientEntity client;
}

// try this
@Entity
class TarifEntity {
  @Id
  private int id;
  private int clientId;
}

Then load a tarif in your service (or controller) and using the clientId load also the client from its JPA repository and combine them in a single response. The obvious disadvantage is an additional call to a database (two instead of one). The obvious advantage is that you decide in your service (or controller) based on user’s intent whether it is necessary to actually load the client information.

For example, listing tarifs for a client (whose information you already have on screen) should not load and return client information again and again for each tarif.

However, if you need to list all tarifs for all clients in a single table (which is a weird requirement), then you might need a different JPA model, and thus a different projection. You can have two projections on the same database table, and use one for writes and the other for reads (with joins).

HTH,
David

2 Likes

Thank you so much @BribedSeeker904 that now makes so much sense , even using identifiers only instead of having entity ease the foreignKey constraints that causes issue with the eventual consistency

Thanks so much

1 Like