2

With org.springframework.kafka:spring-kafka up to version 2.7.9, my Spring-Boot application (consuming/producing Avro from/to Kafka) starts fine, having these environment variables set:

  - name: SPRING_KAFKA_CONSUMER_PROPERTIES_SCHEMA_REGISTRY_URL
    value: "http://avro-schema-registry.core-kafka.svc.cluster.local:8081"
  - name: SPRING_KAFKA_PRODUCER_PROPERTIES_SCHEMA_REGISTRY_URL
    value: "http://avro-schema-registry.core-kafka.svc.cluster.local:8081"

But with version 2.8.2 (same with 2.8.1 and 2.8.0), I get the following error:

org.apache.kafka.common.config.ConfigException: Missing required configuration "schema.registry.url" which has no default value.

Full error from the logs:

2022-01-18 07:15:10,162 [main] ERROR SpringApplication - Application run failed
org.springframework.context.ApplicationContextException: Failed to start bean 'org.springframework.kafka.config.internalKafkaListenerEndpointRegistry'; nested exception is org.apache.kafka.common.config.ConfigException: Missing required configuration "schema.registry.url" which has no default value.
    at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:181)
    at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54)
    at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356)
    at java.base/java.lang.Iterable.forEach(Unknown Source)
    at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155)
    at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123)
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:935)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:338)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332)
    at com.acme.foo.bar.ApplicationKt.main(Application.kt:52)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
    at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
Caused by: org.apache.kafka.common.config.ConfigException: Missing required configuration "schema.registry.url" which has no default value.
    at org.apache.kafka.common.config.ConfigDef.parseValue(ConfigDef.java:478)
    at org.apache.kafka.common.config.ConfigDef.parse(ConfigDef.java:468)
    at org.apache.kafka.common.config.AbstractConfig.<init>(AbstractConfig.java:108)
    at org.apache.kafka.common.config.AbstractConfig.<init>(AbstractConfig.java:129)
    at io.confluent.kafka.serializers.AbstractKafkaSchemaSerDeConfig.<init>(AbstractKafkaSchemaSerDeConfig.java:211)
    at io.confluent.kafka.serializers.KafkaAvroDeserializerConfig.<init>(KafkaAvroDeserializerConfig.java:58)
    at io.confluent.kafka.serializers.KafkaAvroDeserializer.configure(KafkaAvroDeserializer.java:50)
    at org.springframework.kafka.support.serializer.ErrorHandlingDeserializer.configure(ErrorHandlingDeserializer.java:139)
    at org.springframework.kafka.core.DefaultKafkaConsumerFactory.lambda$keyDeserializerSupplier$5(DefaultKafkaConsumerFactory.java:142)
    at org.springframework.kafka.core.DefaultKafkaConsumerFactory.createRawConsumer(DefaultKafkaConsumerFactory.java:415)
    at org.springframework.kafka.core.DefaultKafkaConsumerFactory.createKafkaConsumer(DefaultKafkaConsumerFactory.java:384)
    at org.springframework.kafka.core.DefaultKafkaConsumerFactory.createConsumerWithAdjustedProperties(DefaultKafkaConsumerFactory.java:360)
    at org.springframework.kafka.core.DefaultKafkaConsumerFactory.createKafkaConsumer(DefaultKafkaConsumerFactory.java:327)
    at org.springframework.kafka.core.DefaultKafkaConsumerFactory.createConsumer(DefaultKafkaConsumerFactory.java:304)
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.<init>(KafkaMessageListenerContainer.java:758)
    at org.springframework.kafka.listener.KafkaMessageListenerContainer.doStart(KafkaMessageListenerContainer.java:344)
    at org.springframework.kafka.listener.AbstractMessageListenerContainer.start(AbstractMessageListenerContainer.java:430)
    at org.springframework.kafka.listener.ConcurrentMessageListenerContainer.doStart(ConcurrentMessageListenerContainer.java:209)
    at org.springframework.kafka.listener.AbstractMessageListenerContainer.start(AbstractMessageListenerContainer.java:430)
    at org.springframework.kafka.config.KafkaListenerEndpointRegistry.startIfNecessary(KafkaListenerEndpointRegistry.java:331)
    at org.springframework.kafka.config.KafkaListenerEndpointRegistry.start(KafkaListenerEndpointRegistry.java:276)
    at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178)
    ... 22 common frames omitted

I don't see a remark about such a change in the release notes of spring-kafka. And idea what I might be doing wrong?

Tobias Hermann
  • 9,936
  • 6
  • 61
  • 134

2 Answers2

0

Ok, the trick is to simply not provide an explicit version for spring-kafka (in my case in the build.gradle.kts), but let the Spring dependency management (id("io.spring.dependency-management") version "1.0.11.RELEASE") choose the appropriate one.

2.7.7 is the version that is then currently chosen automatically (with Spring Boot version 2.5.5).

Tobias Hermann
  • 9,936
  • 6
  • 61
  • 134
0

I met the same issue. And after debugging into the code, I found that there is one change in Spring Kafka 2.8 https://github.com/spring-projects/spring-kafka/commit/852c447442c9ac3a4eb41e2ddbcfc83ebe8c97da This will cause a reconfiguration of your serializer and deserializer, which won't work for avro ones.

Starting with version 2.8, if you provide serializers as objects (in the constructor or via the setters), the factory will invoke the configure() method to configure them with the configuration properties.

There is also a related discussion in Spring Kafka serialiser config

Looking at https://github.com/spring-projects/spring-kafka/issues/2274 I think this issue will be fixed by providing an extra option to disable the reconfiguration.

public DefaultKafkaConsumerFactory(Map<String, Object> configs,
            @Nullable Supplier<Deserializer<K>> keyDeserializerSupplier,
            @Nullable Supplier<Deserializer<V>> valueDeserializerSupplier, boolean configureDeserializers) {

        this.configs = new ConcurrentHashMap<>(configs);
        this.configureDeserializers = configureDeserializers;
        this.keyDeserializerSupplier = keyDeserializerSupplier(keyDeserializerSupplier);
        this.valueDeserializerSupplier = valueDeserializerSupplier(valueDeserializerSupplier);
    }
ts0411
  • 1