The default kafka producer factory bean gets kafka properties by calling KafkaProperties.buildProducerProperties method.
@Bean
@ConditionalOnMissingBean(ProducerFactory.class)
public DefaultKafkaProducerFactory<?, ?> kafkaProducerFactory(KafkaConnectionDetails connectionDetails,
ObjectProvider<DefaultKafkaProducerFactoryCustomizer> customizers, ObjectProvider<SslBundles> sslBundles) {
Map<String, Object> properties = this.properties.buildProducerProperties(sslBundles.getIfAvailable());
...
}
Behind the scenes this calls Ssl.buildProperties method
public Map<String, Object> buildProperties(SslBundles sslBundles) {
validate();
...
which calls validate() and prematurely validates some things
private void validate() {
MutuallyExclusiveConfigurationPropertiesException.throwIfMultipleNonNullValuesIn((entries) -> {
entries.put("spring.kafka.ssl.key-store-key", getKeyStoreKey());
entries.put("spring.kafka.ssl.key-store-location", getKeyStoreLocation());
});
but these properties can still be added, modified or deleted by the customizers in the kafkaProducerFactory method
@Bean
@ConditionalOnMissingBean(ProducerFactory.class)
public DefaultKafkaProducerFactory<?, ?> kafkaProducerFactory(KafkaConnectionDetails connectionDetails,
ObjectProvider<DefaultKafkaProducerFactoryCustomizer> customizers, ObjectProvider<SslBundles> sslBundles) {
...
customizers.orderedStream().forEach((customizer) -> customizer.customize(factory));
return factory;
}
These validations should be done after the customizers.
Comment From: wilkinsona
Thanks for the report but I'm afraid I don't think I understand the problem. How can a DefaultKafkaProducerFactoryCustomizer change the properties that have been bound to KafkaProperties? Are you suggesting that the changes made to the producer's configs by any customizer should be mapped back to KafkaProperties and then the validation should be performed?
Comment From: geertvb
The properties used by kafka producer factory is a combination of the properties generated by the buildProperties method and some customizations. The final set of properties should be validated. The properties set produced by buildProperties may not be valid but after the customizations are applied it may and vice versa. I will provide a minimal example if you prefer.
Comment From: wilkinsona
The properties set produced by buildProperties may not be valid but after the customizations are applied it may and vice versa.
The intention of the customization is that it allows you to configure things that cannot be configured using the properties. If you're partially configuring something using properties and then completing and correcting it using a customizer, we'd recommend configuring it all using properties or all using a customizer.
I will provide a minimal example if you prefer.
Yes please, it may demonstrate a situation where a split approach is required. If it does, we may want to consider some additional properties to avoid the need.
Comment From: geertvb
Regardless of the intention of the customizer, the best moment to validate the state of a constructed bean is when all configuration has been applied. I consider other approaches a workaround and we already have a workaround on our side. I just wanted to report this conceptual problem.
Comment From: wilkinsona
Regardless of the intention of the customizer, the best moment to validate the state of a constructed bean is when all configuration has been applied
That's what we're doing. The validation is being applied to KafkaProperties at a time when all properties have been bound to it.
I just wanted to report this conceptual problem.
Thanks. I don't think such a problem exists as there's some separation between the properties and their validation and the customization of a producer factory so I'll close this one.
Comment From: geertvb
KafkaProperties is not a (real) bean, just a properties container/helper. Validation should be at the right moment in the kafkaProducerFactory bean its lifecycle (e.g. afterPropertiesSet)