private void registerSagaManagers(Map<String, List<Function<Configuration, EventHandlerInvoker>>> handlerInvokers) { sagaConfigurations.forEach(sc -> { SagaConfiguration<?> sagaConfig = sc.initialize(configuration); String processingGroup = selectProcessingGroupByType(sagaConfig.type()); String processorName = processorNameForProcessingGroup(processingGroup); handlerInvokers.computeIfAbsent(processorName, k -> new ArrayList<>()) .add(c -> sagaConfig.manager()); }); }
/** * Initialize a configuration for a Saga of given {@code sagaType}, using a Tracking Event Processor (with provided * name) to process incoming Events. Note that a Token Store should be configured in the global configuration, or * the Saga Manager will default to an in-memory token store, which is not recommended for production environments. * * @param sagaType The type of Saga to handle events with * @param processingGroup The name of the processing group to be used for this saga * @param <S> The type of Saga configured in this configuration * @return a SagaConfiguration instance, ready for further configuration */ public static <S> SagaConfiguration<S> trackingSagaManager(Class<S> sagaType, String processingGroup) { return trackingSagaManager(sagaType, processingGroup, Configuration::eventBus); }
/** * Initialize a configuration for a Saga of given {@code sagaType}, using a Subscribing Event Processor to process * incoming Events. * * @param sagaType The type of Saga to handle events with * @param <S> The type of Saga configured in this configuration * @return a SagaConfiguration instance, ready for further configuration */ public static <S> SagaConfiguration<S> subscribingSagaManager(Class<S> sagaType) { return subscribingSagaManager(sagaType, Configuration::eventBus); }
/** * Initialize a configuration for a Saga of given {@code sagaType}, using a Tracking Event Processor to process * incoming Events from a Message Source provided by given {@code messageSourceBuilder}. Note that a Token Store * should be configured in the global configuration, or the Saga Manager will default to an in-memory token store, * which is not recommended for production environments. * * @param sagaType The type of Saga to handle events with * @param messageSourceBuilder The function providing the message source based on the configuration * @param <S> The type of Saga configured in this configuration * @return a SagaConfiguration instance, ready for further configuration */ public static <S> SagaConfiguration<S> trackingSagaManager( Class<S> sagaType, Function<Configuration, StreamableMessageSource<TrackedEventMessage<?>>> messageSourceBuilder) { ProcessorInfo processorInfo = new ProcessorInfo(true, ProcessorInfo.ProcessorType.TRACKING, processingGroupName(sagaType)); return new SagaConfiguration<>(sagaType, processorInfo, TrackingEventProcessor.class, messageSourceBuilder, c -> null, c -> null); }
/** * Returns the processor that processed events for the Saga in this Configuration. * * @return The EventProcessor defined in this Configuration * * @throws IllegalStateException when this configuration hasn't been initialized yet */ public EventProcessor getProcessor() { return eventProcessingConfiguration().eventProcessorByProcessingGroup(processorInfo.getProcessingGroup()) .orElse(null); }
/** * Returns the {@link SagaConfiguration} for the given {@code sagaType}. If no configuration has been provided for * a Saga of this type, {@code null} is returned. * * @param sagaType the type of Saga to return the configuration for. * @param <T> the type of Saga * @return the configuration for the Saga, or {@code null} if not found */ @SuppressWarnings("unchecked") default <T> SagaConfiguration<T> sagaConfiguration(Class<T> sagaType) { return (SagaConfiguration<T>) sagaConfigurations().stream().filter(c -> sagaType.equals(c.type())).findFirst().orElse(null); }
/** * Initialize a configuration for a Saga of given {@code sagaType}, using a Tracking Event Processor (with provided * name) to process incoming Events from a Message Source provided by given {@code messageSourceBuilder}. Note that * a Token Store should be configured in the global configuration, or the Saga Manager will default to an in-memory * token store, which is not recommended for production environments. * * @param sagaType The type of Saga to handle events with * @param processingGroup The name of the processing group to be used for this saga * @param messageSourceBuilder The function providing the message source based on the configuration * @param <S> The type of Saga configured in this configuration * @return a SagaConfiguration instance, ready for further configuration */ public static <S> SagaConfiguration<S> trackingSagaManager(Class<S> sagaType, String processingGroup, Function<Configuration, StreamableMessageSource<TrackedEventMessage<?>>> messageSourceBuilder) { ProcessorInfo processorInfo = new ProcessorInfo(false, ProcessorInfo.ProcessorType.TRACKING, processingGroup); return new SagaConfiguration<>(sagaType, processorInfo, TrackingEventProcessor.class, messageSourceBuilder, c -> null, c -> null); }
/** * Initialize a configuration for a Saga of given {@code sagaType}, using a Tracking Event Processor to process * incoming Events. Note that a Token Store should be configured in the global configuration, or the Saga Manager * will default to an in-memory token store, which is not recommended for production environments. * * @param sagaType The type of Saga to handle events with * @param <S> The type of Saga configured in this configuration * @return a SagaConfiguration instance, ready for further configuration */ public static <S> SagaConfiguration<S> trackingSagaManager(Class<S> sagaType) { return trackingSagaManager(sagaType, Configuration::eventBus); }
/** * Initialize a configuration for a Saga of given {@code sagaType}, using a Subscribing Event Processor to process * incoming Events from the message source provided by given {@code messageSourceBuilder} * * @param sagaType The type of Saga to handle events with * @param messageSourceBuilder The function providing the message source based on the configuration * @param <S> The type of Saga configured in this configuration * @return a SagaConfiguration instance, ready for further configuration */ public static <S> SagaConfiguration<S> subscribingSagaManager( Class<S> sagaType, Function<Configuration, SubscribableMessageSource<EventMessage<?>>> messageSourceBuilder) { return subscribingSagaManager(sagaType, messageSourceBuilder, c -> DirectEventProcessingStrategy.INSTANCE); }
/** * Initialize a configuration for a Saga of given {@code sagaType}, using a Subscribing Event Processor to process * incoming Events from the message source provided by given {@code messageSourceBuilder}. * <p> * This methods allows a custom {@link EventProcessingStrategy} to be provided, in case handlers shouldn't be * invoked in the thread that delivers the message. * * @param sagaType The type of Saga to handle events with * @param messageSourceBuilder The function providing the message source based on the configuration * @param eventProcessingStrategy The strategy to use to invoke the event handlers. * @param <S> The type of Saga configured in this configuration * @return a SagaConfiguration instance, ready for further configuration */ public static <S> SagaConfiguration<S> subscribingSagaManager( Class<S> sagaType, Function<Configuration, SubscribableMessageSource<EventMessage<?>>> messageSourceBuilder, Function<Configuration, EventProcessingStrategy> eventProcessingStrategy) { ProcessorInfo processorInfo = new ProcessorInfo(true, ProcessorInfo.ProcessorType.SUBSCRIBING, processingGroupName(sagaType)); return new SagaConfiguration<>(sagaType, processorInfo, SubscribingEventProcessor.class, c -> null, messageSourceBuilder, eventProcessingStrategy); }
/** * Registers the handler interceptor provided by the given {@code handlerInterceptorBuilder} function with * the processor defined in this configuration. * * @param handlerInterceptorBuilder The function to create the interceptor based on the current configuration * @return this SagaConfiguration instance, ready for further configuration * * @deprecated use {@link EventProcessingConfiguration#registerHandlerInterceptor(String, Function)} instead */ @Deprecated public SagaConfiguration<S> registerHandlerInterceptor( Function<Configuration, MessageHandlerInterceptor<? super EventMessage<?>>> handlerInterceptorBuilder) { if (config != null) { eventProcessingConfiguration().registerHandlerInterceptor(processorInfo.getProcessingGroup(), handlerInterceptorBuilder); } else { handlerInterceptors.add(handlerInterceptorBuilder); } return this; }
/** * Returns the {@link SagaConfiguration} for the given {@code sagaType}. If no configuration has been provided for * a Saga of this type, {@code null} is returned. * * @param sagaType the type of Saga to return the configuration for. * @param <T> the type of Saga * @return the configuration for the Saga, or {@code null} if not found */ @SuppressWarnings("unchecked") default <T> SagaConfiguration<T> sagaConfiguration(Class<T> sagaType) { return (SagaConfiguration<T>) sagaConfigurations().stream().filter(c -> sagaType.equals(c.type())).findFirst().orElse(null); }
/** * Initialize a configuration for a Saga of given {@code sagaType}, using a Subscribing Event Processor (with * provided name) to process incoming Events from the message source provided by given {@code * messageSourceBuilder}. * <p> * This method allows a custom {@link EventProcessingStrategy} to be provided, in case handlers shouldn't be * invoked in the thread that delivers the message. * * @param sagaType The type of Saga to handle events with * @param processingGroup The name of the processing group to be used for this saga * @param messageSourceBuilder The function providing the message source based on the configuration * @param eventProcessingStrategy The strategy to use to invoke the event handlers. * @param <S> The type of Saga configured in this configuration * @return a SagaConfiguration instance, ready for further configuration */ public static <S> SagaConfiguration<S> subscribingSagaManager( Class<S> sagaType, String processingGroup, Function<Configuration, SubscribableMessageSource<EventMessage<?>>> messageSourceBuilder, Function<Configuration, EventProcessingStrategy> eventProcessingStrategy) { ProcessorInfo processorInfo = new ProcessorInfo(false, ProcessorInfo.ProcessorType.SUBSCRIBING, processingGroup); return new SagaConfiguration<>(sagaType, processorInfo, SubscribingEventProcessor.class, c -> null, messageSourceBuilder, eventProcessingStrategy); }
@Bean public SagaConfiguration<SellTradeManagerSaga> sellTradeSagaConfiguration() { return SagaConfiguration.trackingSagaManager(SellTradeManagerSaga.class); } }
/** * Initialize a configuration for a Saga of given {@code sagaType}, using a Subscribing Event Processor (with * provided name) to process incoming Events. * * @param sagaType The type of Saga to handle events with * @param processingGroup The name of the processing group to be used for this saga * @param <S> The type of Saga configured in this configuration * @return a SagaConfiguration instance, ready for further configuration */ public static <S> SagaConfiguration<S> subscribingSagaManager(Class<S> sagaType, String processingGroup) { return subscribingSagaManager(sagaType, processingGroup, Configuration::eventBus, c -> DirectEventProcessingStrategy.INSTANCE); }
private void registerSagaManagers(Map<String, List<Function<Configuration, EventHandlerInvoker>>> handlerInvokers) { sagaConfigurations.forEach(sc -> { SagaConfiguration<?> sagaConfig = sc.initialize(configuration); String processingGroup = selectProcessingGroupByType(sagaConfig.type()); String processorName = processorNameForProcessingGroup(processingGroup); handlerInvokers.computeIfAbsent(processorName, k -> new ArrayList<>()) .add(c -> sagaConfig.manager()); }); }
@Override public void initialize(Configuration config) { this.config = config; eventProcessingConfiguration().registerHandlerInvoker(processorInfo.getProcessingGroup(), c -> sagaManager.get()); eventProcessingConfiguration().registerTokenStore(processorInfo.getProcessingGroup(), c -> tokenStore.get()); eventProcessingConfiguration().configureMessageMonitor(processorInfo.getProcessingGroup(), c -> (MessageMonitor<Message<?>>) messageMonitor.get()); eventProcessingConfiguration().configureErrorHandler(processorInfo.getProcessingGroup(), c -> errorHandler.get()); eventProcessingConfiguration().configureRollbackConfiguration(processorInfo.getProcessingGroup(), c -> rollbackConfiguration.get()); eventProcessingConfiguration().configureTransactionManager(processorInfo.getProcessingGroup(), c -> transactionManager.get()); handlerInterceptors.forEach(i -> eventProcessingConfiguration() .registerHandlerInterceptor(processorInfo.getProcessingGroup(), i)); if (processorInfo.isCreateNewProcessor()) { switch (processorInfo.getType()) { case TRACKING: eventProcessingConfiguration().registerEventProcessor(processorInfo.getProcessingGroup(), this::buildTrackingEventProcessor); break; case SUBSCRIBING: eventProcessingConfiguration().registerEventProcessor(processorInfo.getProcessingGroup(), this::buildSubscribingEventProcessor); break; default: throw new IllegalStateException("Unsupported event processor type."); } } }
@Bean public SagaConfiguration<BuyTradeManagerSaga> buyTradeSagaConfiguration() { return SagaConfiguration.trackingSagaManager(BuyTradeManagerSaga.class); }
.registerModule(queryModelConfiguration) .registerModule(commandPublisherConfiguration) .registerModule(SagaConfiguration.subscribingSagaManager(SellTradeManagerSaga.class)) .registerModule(SagaConfiguration.subscribingSagaManager(BuyTradeManagerSaga.class)) .buildConfiguration(); configuration.start();
@Bean public SagaConfiguration bankTransferManagementSagaConfiguration() { return SagaConfiguration.trackingSagaManager(BankTransferManagementSaga.class); }