Search code examples
spring-bootspring-kafka

Spring Boot Auto Configuration Failed Loading Spring Kafka Properties


Spring boot failed to load properties. Here are the properties that i am using through the yaml file.

 spring:
  kafka:
    bootstrap-servers: localhost:9092
    consumer:
      auto-commit-interval: 100
      enable-auto-commit: true
      group-id: ********************
      auto-offset-reset: earliest
      value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
    producer:
      batch-size: 16384
      buffer-memory: 33554432
      retries: 0
      value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
    listener:
      poll-timeout: 20000

The exception i am getting is this

Caused by: java.lang.IllegalAccessException: Class org.apache.kafka.common.utils.Utils can not access a member of class org.springframework.kafka.support.serializer.JsonDeserializer with modifiers "protected"

I think the constructor is protected. Please provide a way to instantiate this.


Solution

  • That's correct. See:

    protected JsonDeserializer() {
            this((Class<T>) null);
        }
    
        protected JsonDeserializer(ObjectMapper objectMapper) {
            this(null, objectMapper);
        }
    
        public JsonDeserializer(Class<T> targetType) {
            this(targetType, new ObjectMapper());
            this.objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
            this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        }
    

    The JsonDeserializer isn't designed to be instantiated by the default constructor because it needs to know the targetType to deserialize.

    You can extend this class to your particular type:

    public class FooJsonDeserializer extends JsonDeserializer<Foo> { }
    

    and use already this as class value for that value-deserializer property.

    Or you can consider to customize the DefaultKafkaConsumerFactory:

    @Bean
    public ConsumerFactory<?, ?> kafkaConsumerFactory(KafkaProperties properties) {
        Map<String, Object> consumerProperties = properties.buildConsumerProperties();
        consumerProperties.put(CommonClientConfigs.METRIC_REPORTER_CLASSES_CONFIG,
                MyConsumerMetricsReporter.class);
        DefaultKafkaConsumerFactory<Object, Object> consumerFactory =
              new DefaultKafkaConsumerFactory<>(consumerProperties);
        consumerFactory.setValueDeserializer(new JsonDeserializer<>(Foo.class));
        return consumerFactory;
    }