I am using new @ServiceConnection annotation to manage KafkaContainer
in my tests and it works as expected - KafkaContainerConnectionDetails
is used during auto configuration to override bootstrap servers property.
Now, i also want to use custom GenericContainer
subclass i created - SchemaRegistryContainer
.
I would also like to manage this container with @ServiceConnection
annotation, but it crashes with ConnectionDetailsNotFoundException: No ConnectionDetails found for source '@ServiceConnection source for Bean 'schemaRegistryContainer'
.
I would like have my own custom ConnectionDetails
(or some alternative way) for this @ServiceConnection
, so that i can modify application properties i need when SchemaRegistryContainer
starts. In this specific case, i need to modify property spring.kafka.consumer.properties.schema-registry-url
with url from container.
Is this there a way to achieve this with @ServiceDefinition
?
I dont want to fall back to using static fields and @DynamicPropertySource
.
My test configuration
@TestConfiguration(proxyBeanMethods = false)
public class ContainerConfig {
public static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("confluentinc/cp-kafka");
public static final String CONFLUENT_PLATFORM_VERSION = "7.4.1";
@Bean
@ServiceConnection
KafkaContainer kafkaContainer() {
return new KafkaContainer(DEFAULT_IMAGE_NAME.withTag(CONFLUENT_PLATFORM_VERSION));
}
@Bean
@ServiceConnection
SchemaRegistryContainer schemaRegistryContainer(KafkaContainer kafkaContainer) {
return new SchemaRegistryContainer(CONFLUENT_PLATFORM_VERSION, kafkaContainer);
}
}
SchemaRegistryContainer:
public class SchemaRegistryContainer extends GenericContainer<SchemaRegistryContainer> {
private static final int PORT = 8081;
public SchemaRegistryContainer(String confluentVersion, KafkaContainer kafka) {
super("confluentinc/cp-schema-registry:" + confluentVersion);
withExposedPorts(PORT);
dependsOn(kafka);
withEnv("SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS", kafka.getBootstrapServers());
}
public String getSchemaRegistryUrl() {
return "http://" + getHost() + ":" + getMappedPort(PORT);
}
}
I found out i was misunderstanding what @ServiceConnection
was doing.
In fact, this annotation is not needed at all, if i dont have custom ConnectionDetails
but i still can use container as @Bean.
For customizing properties after contaner starts, i used DynamicPropertyRegistry. This is in fact also mentioned in docs: https://docs.spring.io/spring-boot/docs/3.1.0/reference/htmlsingle/#features.testing.testcontainers.at-development-time.dynamic-properties
New code:
@Bean
SchemaRegistryContainer schemaRegistryContainer(KafkaContainer kafkaContainer, DynamicPropertyRegistry dynamicPropertyRegistry) {
SchemaRegistryContainer schemaRegistryContainer = new SchemaRegistryContainer(CONFLUENT_PLATFORM_VERSION, kafkaContainer);
dynamicPropertyRegistry.add("spring.kafka.consumer.properties.schema.registry.url", schemaRegistryContainer::getTarget);
dynamicPropertyRegistry.add("spring.kafka.producer.properties.schema.registry.url", schemaRegistryContainer::getTarget);
return schemaRegistryContainer;
}