AxonFramework / AxonFramework

Framework for Evolutionary Message-Driven Microservices on the JVM
https://axoniq.io/
Apache License 2.0
3.32k stars 790 forks source link

Allow disabling the default CorrelationDataProvider in AxonAutoConfiguration when registering a CorrelationDataInterceptor #3118

Closed hahawin closed 1 month ago

hahawin commented 1 month ago

Enhancement Description

Provide a way to disable the default CorrelationDataProvider when registering a custom CorrelationDataProvider through a CorrelationDataInterceptor

Current Behaviour

Currently the AxonAutoConfiguration provides a default CorrelationDataProvider (an instance of MessageOriginProvider) when no other CorrelationDataProvider is present as a spring bean (using @ConditionalOnMissingBean). Providing a bean with a custom CorrelationDataProvider disables this default provider. However, CorrelationDataProviders can also be registered by using a CorrelationDataInterceptor. In this case, the default CorrelationDataProvider is not disabled.

Wanted Behaviour

Provide a way to disable the default CorrelationDataProvider when using a CorrelationDataInterceptor, either automatically (by detecting the presence of CorrelationDataInterceptor beans) or by making this behaviour explicitly configurable.

Automatically detecting the presence of a CorrelationDataInterceptor bean (e.g. by using a second @ConditionalOnMissingBean on the declaration of the default provider) seems like a very straightforward solution though that would technically be a breaking change.

smcvb commented 1 month ago

First off, @hahawin, thanks for filing this issue with us!

Secondly, I have an (I assume) easy question: why do you need this? I get the feeling that the workaround is pretty straightfoward, is the sole thing you'd have to do is to provide a CorrelationDataProvider bean in your Application Context to replace the default. So, my question is really about understanding the benefits of such an enhancement.

Thirdly, note that the suggested Spring-specific solution would be a behavioral breaking change to other users. If when this is implemented and somebody upgrades to the most recent version of Axon Framework, they'd all of a sudden lose their default MessageOriginProvider. Hence, the suggested bean approach doesn't seem to be a good fit to me to be honest.

Regardless, I am curious on your intent for creating this issue, so be sure to share!

hahawin commented 1 month ago

We would like to have this feature mostly for convenience and keeping our codebase a little cleaner and more consistent. We currently exclusively use CorrelationDataInterceptors as they are slightly more flexible: we have multiple command- and event busses in the same spring context and declaring a CorrelationDataProvider bean will automatically register it with all of them whereas with an interceptor we can have different ones per bus. We could change one of our CorrelationDataInterceptors that is used on all busses to a CorrelationDataProvider but that would introduce some inconsistency as we would then have a mix of CorrelationDataInterceptors and CorrelationDataProviders (and I can already see someone try to "fix" this inconsistency in the future without realising that would enable the default provider again)

As to why we would like to disable the default MessageOriginProvider is simply because we would like to use the "traceId" key ourselves. We could use a different key but having 2 different traceId keys will be confusing.

smcvb commented 1 month ago

Thanks for the explanation, @hahawin! While mulling over your scenario just now, I came up with another suggestion to replace the default CorrelationDataProvider collection without interacting with the CorrelationDataInterceptor.

Axon Framework's Configurer contains the configureCorrelationDataProviders(Function<Configuration, List<CorrelationDataProvider>) method. In the end, Axon's Spring Auto Config will use the List set in the Configurer, so by setting the List through the configureCorrelationDataProviders, you remove the default MessageOriginProvider from the equation. Thus, that will allow you to use the traceId key yourselves if I am not mistaking.

To set this configuration in a Spring environment, you can provide a ConfigurerModule like so:

@Bean
public ConfigurerModule correlationDataProviderModule() {
    return configurer -> configurer.configureCorrelationDataProviders(config -> {
        List<CorrelationDataProvider> correlationDataProviders = new ArrayList<>();
        correlationDataProviders.add(new MyCorrelationDataProvider());
        // ...
        return correlationDataProviders;
    });
}

Can you tell me whether that'll do the trick for you, @hahawin?

hahawin commented 1 month ago

Hello, sorry for the delay.

This looks like a good solution, thanks for the info!

smcvb commented 3 weeks ago

Hello, sorry for the delay.

This looks like a good solution, thanks for the info!

No worries there, @hahawin. Happy to have helped you further! :-)