All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.quandoo.lib.reactivekafka.spring.KafkaAutoconfiguration.kt Maven / Gradle / Ivy

Go to download

A high level kafka consumer which wrapps the low level api of Kafka Reactor and provides a similar usability like Spring Kafka

There is a newer version: 1.5.1
Show newest version
/**
 *    Copyright (C) 2019 Quandoo GmbH ([email protected])
 *
 *       Licensed under the Apache License, Version 2.0 (the "License");
 *       you may not use this file except in compliance with the License.
 *       You may obtain a copy of the License at
 *
 *           http://www.apache.org/licenses/LICENSE-2.0
 *
 *       Unless required by applicable law or agreed to in writing, software
 *       distributed under the License is distributed on an "AS IS" BASIS,
 *       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *       See the License for the specific language governing permissions and
 *       limitations under the License.
 */
package com.quandoo.lib.reactivekafka.spring

import com.fasterxml.jackson.databind.ObjectMapper
import com.github.daniel.shuy.kafka.jackson.serializer.KafkaJacksonSerializer
import com.google.common.base.Predicate
import com.quandoo.lib.reactivekafka.KafkaProperties
import com.quandoo.lib.reactivekafka.consumer.KafkaConsumer
import com.quandoo.lib.reactivekafka.consumer.listener.KafkaListener
import com.quandoo.lib.reactivekafka.consumer.listener.KafkaListenerFinder
import com.quandoo.lib.reactivekafka.consumer.listener.KafkaListenerMeta
import com.quandoo.lib.reactivekafka.util.KafkaConfigHelper
import org.apache.kafka.common.serialization.StringSerializer
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.config.ConfigurableBeanFactory
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationListener
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.event.ContextRefreshedEvent
import reactor.kafka.sender.KafkaSender
import reactor.kafka.sender.SenderOptions

/**
 * @author Emir Dizdarevic
 * @since 1.0.0
 */
@Configuration
@ConditionalOnClass(ObjectMapper::class)
@EnableConfigurationProperties(KafkaProperties::class)
class KafkaAutoconfiguration {

    @Autowired
    lateinit var configurableBeanFactory: ConfigurableBeanFactory

    @Autowired
    lateinit var objectMapper: ObjectMapper

    @Autowired
    lateinit var applicationConfiguration: ApplicationContext

    @Autowired(required = false)
    // Just to make sure that filters are loaded in the context before the autoconfig is executed
    lateinit var filters: List>

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnAnnotation(annotation = KafkaListener::class)
    fun kafkaListenerFinder(): KafkaListenerFinder<*, *> {
        return AnnotationBasedKafkaListenerFinder(configurableBeanFactory, applicationConfiguration, objectMapper)
    }

    @Bean
    @ConditionalOnMissingBean
    @Suppress("UNCHECKED_CAST")
    @ConditionalOnAnnotation(annotation = KafkaListener::class)
    fun kafkaConsumer(
        kafkaProperties: KafkaProperties,
        kafkaListenerFinder: KafkaListenerFinder
    ): KafkaConsumer {
        return KafkaConsumer(
                kafkaProperties,
                kafkaListenerFinder.findListeners() as List>
        )
    }

    @Bean
    @ConditionalOnBean(KafkaConsumer::class)
    fun springStartupListener(kafkaConsumer: KafkaConsumer): SpringStartupListener {
        return SpringStartupListener(kafkaConsumer)
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "kafka.producer", name = ["max-in-flight"])
    fun kafkaSender(
        kafkaProperties: KafkaProperties,
        objectMapper: ObjectMapper
    ): KafkaSender {
        val producerProps = HashMap()
                .let { KafkaConfigHelper.populateCommonConfig(kafkaProperties, it) }
                .let { KafkaConfigHelper.populateSslConfig(kafkaProperties, it) }
                .let { KafkaConfigHelper.populateSaslConfig(kafkaProperties, it) }

        val senderOptions = SenderOptions.create(producerProps)
                .withKeySerializer(StringSerializer())
                .withValueSerializer(KafkaJacksonSerializer(objectMapper))
                .maxInFlight(kafkaProperties.producer!!.maxInFlight!!.toInt())

        return KafkaSender.create(senderOptions)
    }
}

class SpringStartupListener(private val kafkaConsumer: KafkaConsumer) : ApplicationListener {

    override fun onApplicationEvent(event: ContextRefreshedEvent) {
        kafkaConsumer.start()
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy