10

I'm using Spring Kafka 1.1.2-RELEASE with Spring Boot 1.5.0 RC and I have configured a custom value serialiser/deserialiser class extending org.springframework.kafka.support.serializer.JsonSerializer/org.springframework.kafka.support.serializer.JsonDeserializer. These classes do use a Jackson ObjectMapper which can be provided through the constructor.

Is it somehow possible to inject the ObjectMapper from my Spring context? I have an ObjectMapper configured already which I would like to reuse in the serialiser/deserialiser.

wjans
  • 10,009
  • 5
  • 32
  • 43

3 Answers3

14

You can configure JsonSerializer and JsonDeserializer as @Beans. Inject a desired ObjectMapper to them. And use those beans in the DefaultKafkaProducerFactory and DefaultKafkaConsumerFactory bean definitions:

    @Bean
    public ProducerFactory<Integer, String> producerFactory() {
        DefaultKafkaProducerFactory<Integer, String> producerFactory = 
                new DefaultKafkaProducerFactory<>(producerConfigs());
        producerFactory.setValueSerializer(jsonSerializer());
        return producerFactory;
    }
Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • 1
    Thanks, that will solve my duplication. However, regarding the new autoconfiguration for Kafka in Spring Boot 1.5, I suppose I can use `org.springframework.boot.autoconfigure.kafka.KafkaProperties#buildProducerProperties` to keep all other configuration working, but wouldn't it still be weird to bypass the configured values for `spring.kafka.producer.value-serializer` then? – wjans Jan 24 '17 at 19:46
  • 1
    Yes, you have to reuse `buildProducerProper‌​ties()` for your custom bean. And no, `.producer.value-serializer` is for class, which is instantiated by Kafka on demand. If you want to use your own instance you have only choice to inject it directly. See `KafkaProducer(Map configs, Serializer keySerializer, Serializer valueSerializer)` API on the matter. – Artem Bilan Jan 24 '17 at 19:50
4
@Component
public class ObjectMapperProducerFactoryCustomizer implements DefaultKafkaProducerFactoryCustomizer {

    private final ObjectMapper objectMapper;

    public ObjectMapperProducerFactoryCustomizer(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public void customize(DefaultKafkaProducerFactory<?, ?> producerFactory) {
        if (Objects.nonNull(producerFactory)) {
            producerFactory.setValueSerializer(new JsonSerializer<>(objectMapper));
        }
    }

}
Matthieu
  • 2,736
  • 4
  • 57
  • 87
0

For the reactive non-blocking kafka client the configuration is the following:

@Configuration
@EnableConfigurationProperties(KafkaProperties.class)
public class KafkaConfig {

    @Bean
    public ReactiveKafkaProducerTemplate<String, Object> kafkaProducerTemplate(KafkaProperties p,
                                                                               ObjectMapper objectMapper) {
        return new ReactiveKafkaProducerTemplate<>(
                SenderOptions.<String, Object>create(p.buildProducerProperties())
                        .withValueSerializer(new JsonSerializer<>(objectMapper)));
    }
}

the above implies that you are using the io.projectreactor.kafka dep,

dependencies {
    compile "io.projectreactor.kafka:reactor-kafka"
}
magiccrafter
  • 5,175
  • 1
  • 56
  • 50