/* * Copyright (c) 2005-2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you 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.wso2.carbon.inbound.endpoint.protocol.kafka; import kafka.consumer.*; import org.I0Itec.zkclient.exception.ZkTimeoutException; import org.apache.synapse.SynapseException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.ArrayList; public class KAFKAMessageListener extends AbstractKafkaMessageListener { public KAFKAMessageListener(int threadCount, List<String> topics, Properties kafkaProperties, InjectHandler injectHandler) throws Exception { this.threadCount = threadCount; this.topics = topics; this.kafkaProperties = kafkaProperties; this.injectHandler = injectHandler; } /** * Create the connection with the zookeeper to consume the messages */ public boolean createKafkaConsumerConnector() throws Exception { log.debug("Create the connection and start to consume the streams"); boolean isCreated; try { if (consumerConnector == null) { log.info("Creating Kafka Consumer Connector..."); //set default consumer timeout to 3000ms if it is not set by the user if (!kafkaProperties.containsKey(KAFKAConstants.CONSUMER_TIMEOUT)) { kafkaProperties.put(KAFKAConstants.CONSUMER_TIMEOUT, "3000"); } consumerConnector = Consumer.createJavaConsumerConnector(new ConsumerConfig(kafkaProperties)); log.info("Kafka Consumer Connector is created"); start(); } isCreated = true; } catch (ZkTimeoutException toe) { log.error(" Error in Creating Kafka Consumer Connector | ZkTimeout" + toe.getMessage()); throw new SynapseException( " Error in Creating Kafka Consumer Connector| ZkTimeout"); } catch (Exception e) { log.error(" Error in Creating Kafka Consumer Connector." + e.getMessage(),e); throw new SynapseException(" Error in Creating Kafka Consumer Connector ", e); } return isCreated; } /** * Starts topics consuming the messages,the message can be consumed by topic or topic filter which are white list and black list. */ public void start() throws Exception { log.debug("Start to consume the streams"); try { log.info("Starting KAFKA consumer..."); Map<String, Integer> topicCount = new HashMap<String, Integer>(); if (topics != null && topics.size() > 0) { // Define threadCount thread/s for topic for (String topic : topics) { topicCount.put(topic, threadCount); } Map<String, List<KafkaStream<byte[], byte[]>>> consumerStreams = consumerConnector .createMessageStreams(topicCount); consumerIte = new ArrayList<ConsumerIterator<byte[], byte[]>>(); for (String topic : topics) { List<KafkaStream<byte[], byte[]>> streams = consumerStreams .get(topic); startConsumers(streams); } } else if (kafkaProperties.getProperty(KAFKAConstants.TOPIC_FILTER) != null) { // Define #threadCount thread/s for topic filter List<KafkaStream<byte[], byte[]>> consumerStreams; boolean isFromWhiteList = (kafkaProperties .getProperty(KAFKAConstants.FILTER_FROM_WHITE_LIST) == null || kafkaProperties .getProperty(KAFKAConstants.FILTER_FROM_WHITE_LIST) .isEmpty()) ? Boolean.TRUE : Boolean .parseBoolean(kafkaProperties .getProperty(KAFKAConstants.FILTER_FROM_WHITE_LIST)); if (isFromWhiteList) { consumerStreams = consumerConnector .createMessageStreamsByFilter( new Whitelist( kafkaProperties .getProperty(KAFKAConstants.TOPIC_FILTER)), threadCount); } else { consumerStreams = consumerConnector .createMessageStreamsByFilter( new Blacklist( kafkaProperties .getProperty(KAFKAConstants.TOPIC_FILTER)), threadCount); } startConsumers(consumerStreams); } } catch (Exception e) { log.error("Error while Starting KAFKA consumer." + e.getMessage(),e); throw new SynapseException( "Error while Starting KAFKA consumer.", e); } } /** * Use one stream from kafka stream iterator * * @param streams */ protected void startConsumers(List<KafkaStream<byte[], byte[]>> streams) { if (streams.size() >= 1) { consumerIte.add(streams.get(0).iterator()); } } @Override public void injectMessageToESB(String name) { if (consumerIte.size() == 1) { injectMessageToESB(name, consumerIte.get(0)); } else { log.debug("There are multiple topics to consume from not a single topic"); } } public void injectMessageToESB(String sequenceName,ConsumerIterator<byte[], byte[]> consumerIterator){ byte[] msg = consumerIterator.next().message(); injectHandler.invoke(msg, sequenceName); } @Override public boolean hasNext() { if (consumerIte.size() == 1) { return hasNext(consumerIte.get(0)); } else { log.debug("There are multiple topics to consume from not a single topic,"); } return false; } public boolean hasNext(ConsumerIterator<byte[], byte[]> consumerIterator) { try { return consumerIterator.hasNext(); } catch (ConsumerTimeoutException e) { //exception ignored if (log.isDebugEnabled()) { log.debug("Topic has no new messages to consume."); } return false; } catch (Exception e) { //Message Listening thread is interrupted during server shutdown. This happen during ESB shutdown is // triggered if (log.isDebugEnabled()) { log.debug("Kafka listener is interrupted by server shutdown.", e); } return false; } } @Override public boolean hasMultipleTopicsToConsume() { if (consumerIte.size() > 1) { return true; } else { return false; } } @Override public void consumeMultipleTopics(String name) { for (ConsumerIterator<byte[], byte[]> consumerIterator : consumerIte) { if (hasNext(consumerIterator)) { injectMessageToESB(name, consumerIterator); } } } }