org.springframework.cloud.stream.binder.kafka.config.KafkaBinderConfiguration.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.cloud.stream.binder.kafka.config.KafkaBinderConfiguration.java

Source

/*
 * Copyright 2015-2017 the original author or authors.
 *
 * 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 org.springframework.cloud.stream.binder.kafka.config;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.common.serialization.ByteArrayDeserializer;
import org.apache.kafka.common.utils.AppInfoParser;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.PublicMetrics;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.stream.binder.Binder;
import org.springframework.cloud.stream.binder.kafka.KafkaBinderHealthIndicator;
import org.springframework.cloud.stream.binder.kafka.KafkaBinderJaasInitializerListener;
import org.springframework.cloud.stream.binder.kafka.KafkaBinderMetrics;
import org.springframework.cloud.stream.binder.kafka.KafkaMessageChannelBinder;
import org.springframework.cloud.stream.binder.kafka.admin.AdminUtilsOperation;
import org.springframework.cloud.stream.binder.kafka.admin.Kafka09AdminUtilsOperation;
import org.springframework.cloud.stream.binder.kafka.admin.Kafka10AdminUtilsOperation;
import org.springframework.cloud.stream.binder.kafka.properties.JaasLoginModuleConfiguration;
import org.springframework.cloud.stream.binder.kafka.properties.KafkaBinderConfigurationProperties;
import org.springframework.cloud.stream.binder.kafka.properties.KafkaExtendedBindingProperties;
import org.springframework.cloud.stream.binder.kafka.provisioning.KafkaTopicProvisioner;
import org.springframework.cloud.stream.config.codec.kryo.KryoCodecAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.integration.codec.Codec;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
import org.springframework.kafka.support.LoggingProducerListener;
import org.springframework.kafka.support.ProducerListener;
import org.springframework.util.ObjectUtils;

/**
 * @author David Turanski
 * @author Marius Bogoevici
 * @author Soby Chacko
 * @author Mark Fisher
 * @author Ilayaperumal Gopinathan
 * @author Henryk Konsek
 */
@Configuration
@ConditionalOnMissingBean(Binder.class)
@Import({ KryoCodecAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class })
@EnableConfigurationProperties({ KafkaBinderConfigurationProperties.class, KafkaExtendedBindingProperties.class })
public class KafkaBinderConfiguration {

    protected static final Log logger = LogFactory.getLog(KafkaBinderConfiguration.class);

    @Autowired
    private Codec codec;

    @Autowired
    private KafkaBinderConfigurationProperties configurationProperties;

    @Autowired
    private KafkaExtendedBindingProperties kafkaExtendedBindingProperties;

    @Autowired
    private ProducerListener producerListener;

    @Autowired
    private ApplicationContext context;

    @Autowired(required = false)
    private AdminUtilsOperation adminUtilsOperation;

    @Bean
    KafkaTopicProvisioner provisioningProvider() {
        return new KafkaTopicProvisioner(this.configurationProperties, this.adminUtilsOperation);
    }

    @Bean
    KafkaMessageChannelBinder kafkaMessageChannelBinder() {
        KafkaMessageChannelBinder kafkaMessageChannelBinder = new KafkaMessageChannelBinder(
                this.configurationProperties, provisioningProvider());
        kafkaMessageChannelBinder.setCodec(this.codec);
        kafkaMessageChannelBinder.setProducerListener(producerListener);
        kafkaMessageChannelBinder.setExtendedBindingProperties(this.kafkaExtendedBindingProperties);
        return kafkaMessageChannelBinder;
    }

    @Bean
    @ConditionalOnMissingBean(ProducerListener.class)
    ProducerListener producerListener() {
        return new LoggingProducerListener();
    }

    @Bean
    KafkaBinderHealthIndicator healthIndicator(KafkaMessageChannelBinder kafkaMessageChannelBinder) {
        Map<String, Object> props = new HashMap<>();
        props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, ByteArrayDeserializer.class);
        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, ByteArrayDeserializer.class);
        if (!ObjectUtils.isEmpty(configurationProperties.getConsumerConfiguration())) {
            props.putAll(configurationProperties.getConsumerConfiguration());
        }
        if (!props.containsKey(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG)) {
            props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,
                    this.configurationProperties.getKafkaConnectionString());
        }
        ConsumerFactory<?, ?> consumerFactory = new DefaultKafkaConsumerFactory<>(props);
        return new KafkaBinderHealthIndicator(kafkaMessageChannelBinder, consumerFactory);
    }

    @Bean
    public PublicMetrics kafkaBinderMetrics(KafkaMessageChannelBinder kafkaMessageChannelBinder) {
        return new KafkaBinderMetrics(kafkaMessageChannelBinder, configurationProperties);
    }

    @Bean(name = "adminUtilsOperation")
    @Conditional(Kafka09Present.class)
    @ConditionalOnClass(name = "kafka.admin.AdminUtils")
    public AdminUtilsOperation kafka09AdminUtilsOperation() {
        logger.info("AdminUtils selected: Kafka 0.9 AdminUtils");
        return new Kafka09AdminUtilsOperation();
    }

    @Bean(name = "adminUtilsOperation")
    @Conditional(Kafka10Present.class)
    @ConditionalOnClass(name = "kafka.admin.AdminUtils")
    public AdminUtilsOperation kafka10AdminUtilsOperation() {
        logger.info("AdminUtils selected: Kafka 0.10 AdminUtils");
        return new Kafka10AdminUtilsOperation();
    }

    @Bean
    public ApplicationListener<?> jaasInitializer() throws IOException {
        return new KafkaBinderJaasInitializerListener();
    }

    static class Kafka10Present implements Condition {

        @Override
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
            return AppInfoParser.getVersion().startsWith("0.10");
        }
    }

    static class Kafka09Present implements Condition {

        @Override
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
            return AppInfoParser.getVersion().startsWith("0.9");
        }
    }

    public static class JaasConfigurationProperties {

        private JaasLoginModuleConfiguration kafka;

        private JaasLoginModuleConfiguration zookeeper;
    }
}