AxonFramework / AxonFramework

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

TestContainer: properties precedence over ServerConnection #3022

Open oleborne opened 2 months ago

oleborne commented 2 months ago

Basic information

Steps to reproduce

  1. write a test using Axon Server test container
    • annotate test class with @TestContainers
    • instantiate a AxonServerContainer as a field of the test class, annotated with @Container and @ServiceConnection
  2. Set the axon.axonserver.servers property in a property file with unknownhost, which is an unresolvable host.

Expected behaviour

The @ServiceConnection annotation has precedence over property based configuration and the Axon Server test container can be accessed by the test.

Actual behaviour

The property axon.axonserver.servers set to unknownhost overrides the configuration generated thanks to the @ServiceConnection annotation.


By looking at JDBC implementation, this precedence is properly handled by having the connection details object (JdbcConnectionDetails) being an interface distinct from the properties object (DataSourceProperties), allowing for a property based implementation of the connection details and a test container based implementation of the same connection details interface. In Axon Framework, AxonServerConfiguration is both bound to a ConfigurationProperties and created by a connection detail factory when using test containers.

gklijs commented 2 months ago

Thanks for reporting this. I would expect the configuration:

@ConditionalOnBean(type = "org.axonframework.springboot.service.connection.AxonServerConnectionDetails")
@Bean
public AxonServerConfiguration axonServerConfigurationWithConnectionDetails(AxonServerConnectionDetails connectionDetails) {
    AxonServerConfiguration configuration = new AxonServerConfiguration();
    configuration.setComponentName(clientName(applicationContext.getId()));
    configuration.setServers(connectionDetails.routingServers());
    return configuration;
}

Would make sure the servers from the AxonServerConnectionDetails is taken before creating the AxonServerConnectionManager. But apparently that doesn't work all the time.

oleborne commented 2 months ago

When debugging, the instance is properly created by this axonServerConfigurationWithConnectionDetails @Bean but it is then later modified by the ConfigurationPropertiesBindingPostProcessor.

From the javadoc for ConfigurationPropertiesBindingPostProcessor:

BeanPostProcessor to bind PropertySources to beans annotated with ConfigurationProperties.

So this does not sound like a ordering issue but tied to the fact that this Bean is annotated with ConfigurationProperties so will always be bound to properties after being instantiated.