I have a usecase where my saga executes a command to run all these reports and I have to maintain the state of each report. There is a report runner worker which will run the reports and generate a report completed notification which my saga will have to consume.
Once all reports are done (Failed / Completed) I have to generate an event for the ending of process.
Can you tell me how I should handle this thing in Saga.
@SagaEventHandler(associationProperty = “id”)
public void on(FirstFinalEvent event) {
firstFinalEventArrived = true;
if (firstFinalEventArrived & secondFinalEventArrived & lastFinalEventArrived ) {
.end(); // end Saga
}
}
@SagaEventHandler(associationProperty = “id”)
public void on(SecondFinalEvent event) {
firstSecondEventArrived = true;
if (firstFinalEventArrived & secondFinalEventArrived & lastFinalEventArrived ) {
.end(); // end Saga
}
}
@SagaEventHandler(associationProperty = “id”)
public void on(LastFinalEvent event) {
lastFinalEventArrived = true;
if (firstFinalEventArrived & secondFinalEventArrived & lastFinalEventArrived ) {
.end(); // end Saga
}
}
Guys,
Please correct me if I’m wrong or there is better way…
Probably it would be nice to have some Condition annotation for several events but each saga logic will be very unique, so, probably it’s not worth do implement such thing.
Sure, I can go with this approach. The point where I am stuck currently is, my listener is able to listen to the events published by the external microservice. But is there a way the saga can directly read those events from the the event bus (In my case rabbit mq).
in Axon, the Event Processor is responsible for reading events from a specific source, and invoking the correct Event Handlers. The latter are the @EventHandler methods that contain your business logic.
By default, Event Processors read from the Event Bus, as in 99% of the cases, that’s where events are published. It is however, very well possible that you want to read from another source. In that case, just instruct the processor to use another source.
Actually, yesterday, I coordinated a hands-on lab that had an exercise exactly for this purpose. You can check it out here: https://github.com/AxonIQ/jfall-axon-labs. The “chat-scaling-out” module is the lab you’d want to be looking at, and on the solution branch, you can see how it’s done. The “RoomParticipantsProjection” handler is configured to read events from RabbitMQ.
I think I got the concept as to how I can manage my business case. The thing that I was missing was publishing the event on the bus. Once I started doing that the Saga was able to suggessfully handle these events from external sources.
I am also facing same issue, the event that I publish on RabbitMQ is visible in my consumer service and is consumed by @EventHandler but @SagaEventHandler is not able to listen to it, could you tell me how exactly did you solve this issue?
Did you define a SagaConfiguration instance (either using correct naming convention, or with the name defined in the @Saga(configurationBean=…) annotation)? On that SagaConfiguration bean, you need to specify the source.
Note that the axon.processors… style configuration does not work for Sagas, yet.
This is the SagaConfiguration Bean we have inside our Configuration file, my Saga is named UserProfileSaga hence the name userProfileSagaConfiguration for the method as per the conventions.
I tried configuring as mentioned in the link you shared, it still does not handle event from @SagaEventHandler but does so from @EventyHandler, below is my configuration class
` @Configuration
public class AxonConfiguration {
private final static Logger logger = LoggerFactory.getLogger(AxonConfiguration.class);
Just to be sure, instead of calling the bean’s creator method, just have it injected as a parameter. Normally, Spring will intercept these calls (even when coming from within the same class), but it may very well be that there are limitations, still.
Just do:
@Bean
public SagaConfiguration userProfileSagaConfiguration(Serializer serializer, SpringAMQPMessageSource source) {
return SagaConfiguration.subscribingSagaManager(UserProfileSaga.class, c -> source);
}
It looks like you have two @RabbitListener annotations listening to the same queue. I only saw one of the annotations, but since you’re defining only a single queue, I make this assumption.
It may very well be that Spring creates a MessageListenerContainer per @RabbitListener annotation, and that the two components are now competing for messages. I recommend removing one of them. If you want to log messages for debugging purposes, do so from within the method you override in the SpringAMQPMessageSource.
Does @StartSaga create a new transaction? And if it does then is it possible that the transaction created by @Transactional on @RabbitListener ends up creating a separate transaction because of which the @SagaListener is not listening to this event while @EventHandler can?