diff --git a/pom.xml b/pom.xml
index 72cacd09c..754452b72 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,6 +23,7 @@
spring-cloud-stream-binder-kafka-docs
spring-cloud-stream-binder-kafka-0.9-test
spring-cloud-stream-binder-kafka-0.10.0-test
+ spring-cloud-stream-binder-kafka-core
diff --git a/spring-cloud-stream-binder-kafka-0.10.0-test/pom.xml b/spring-cloud-stream-binder-kafka-0.10.0-test/pom.xml
index 61a235e25..56a60c4cc 100644
--- a/spring-cloud-stream-binder-kafka-0.10.0-test/pom.xml
+++ b/spring-cloud-stream-binder-kafka-0.10.0-test/pom.xml
@@ -25,6 +25,11 @@
+
+ org.springframework.cloud
+ spring-cloud-stream-binder-kafka-core
+ 1.2.0.BUILD-SNAPSHOT
+
org.springframework.cloud
spring-cloud-stream-binder-kafka
diff --git a/spring-cloud-stream-binder-kafka-0.9-test/src/test/java/org/springframework/cloud/stream/binder/kafka/Kafka09TestBinder.java b/spring-cloud-stream-binder-kafka-0.9-test/src/test/java/org/springframework/cloud/stream/binder/kafka/Kafka09TestBinder.java
index 31ca93e5b..adb53e52a 100644
--- a/spring-cloud-stream-binder-kafka-0.9-test/src/test/java/org/springframework/cloud/stream/binder/kafka/Kafka09TestBinder.java
+++ b/spring-cloud-stream-binder-kafka-0.9-test/src/test/java/org/springframework/cloud/stream/binder/kafka/Kafka09TestBinder.java
@@ -16,8 +16,10 @@
package org.springframework.cloud.stream.binder.kafka;
+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.config.KafkaBinderConfigurationProperties;
+import org.springframework.cloud.stream.binder.kafka.properties.KafkaBinderConfigurationProperties;
+import org.springframework.cloud.stream.binder.kafka.provisioning.KafkaTopicProvisioner;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.kafka.support.LoggingProducerListener;
import org.springframework.kafka.support.ProducerListener;
@@ -35,14 +37,18 @@ public class Kafka09TestBinder extends AbstractKafkaTestBinder {
public Kafka09TestBinder(KafkaBinderConfigurationProperties binderConfiguration) {
try {
- KafkaMessageChannelBinder binder = new KafkaMessageChannelBinder(binderConfiguration);
+ AdminUtilsOperation adminUtilsOperation = new Kafka09AdminUtilsOperation();
+ KafkaTopicProvisioner provisioningProvider =
+ new KafkaTopicProvisioner(binderConfiguration, adminUtilsOperation);
+ provisioningProvider.afterPropertiesSet();
+
+ KafkaMessageChannelBinder binder = new KafkaMessageChannelBinder(binderConfiguration, provisioningProvider);
binder.setCodec(getCodec());
ProducerListener producerListener = new LoggingProducerListener();
binder.setProducerListener(producerListener);
GenericApplicationContext context = new GenericApplicationContext();
context.refresh();
binder.setApplicationContext(context);
- binder.setAdminUtilsOperation(new Kafka09AdminUtilsOperation());
binder.afterPropertiesSet();
this.setBinder(binder);
}
diff --git a/spring-cloud-stream-binder-kafka-0.9-test/src/test/java/org/springframework/cloud/stream/binder/kafka/Kafka_09_BinderTests.java b/spring-cloud-stream-binder-kafka-0.9-test/src/test/java/org/springframework/cloud/stream/binder/kafka/Kafka_09_BinderTests.java
index 583387877..e9c470ce7 100644
--- a/spring-cloud-stream-binder-kafka-0.9-test/src/test/java/org/springframework/cloud/stream/binder/kafka/Kafka_09_BinderTests.java
+++ b/spring-cloud-stream-binder-kafka-0.9-test/src/test/java/org/springframework/cloud/stream/binder/kafka/Kafka_09_BinderTests.java
@@ -34,13 +34,12 @@ import org.junit.ClassRule;
import org.springframework.cloud.stream.binder.Binder;
import org.springframework.cloud.stream.binder.Spy;
import org.springframework.cloud.stream.binder.kafka.admin.Kafka09AdminUtilsOperation;
-import org.springframework.cloud.stream.binder.kafka.config.KafkaBinderConfigurationProperties;
+import org.springframework.cloud.stream.binder.kafka.properties.KafkaBinderConfigurationProperties;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
import org.springframework.kafka.support.KafkaHeaders;
import org.springframework.kafka.test.core.BrokerAddress;
import org.springframework.kafka.test.rule.KafkaEmbedded;
-import org.springframework.retry.RetryOperations;
/**
* Integration tests for the {@link KafkaMessageChannelBinder}.
@@ -93,11 +92,6 @@ public class Kafka_09_BinderTests extends KafkaBinderTests {
return consumerFactory().createConsumer().partitionsFor(topic).size();
}
- @Override
- protected void setMetadataRetryOperations(Binder binder, RetryOperations retryOperations) {
- ((Kafka09TestBinder) binder).getBinder().setMetadataRetryOperations(retryOperations);
- }
-
@Override
protected ZkUtils getZkUtils(KafkaBinderConfigurationProperties kafkaBinderConfigurationProperties) {
final ZkClient zkClient = new ZkClient(kafkaBinderConfigurationProperties.getZkConnectionString(),
diff --git a/spring-cloud-stream-binder-kafka-0.9-test/src/test/java/org/springframework/cloud/stream/binder/kafka/RawModeKafka09BinderTests.java b/spring-cloud-stream-binder-kafka-0.9-test/src/test/java/org/springframework/cloud/stream/binder/kafka/RawModeKafka09BinderTests.java
index 2f058733a..eb386248d 100644
--- a/spring-cloud-stream-binder-kafka-0.9-test/src/test/java/org/springframework/cloud/stream/binder/kafka/RawModeKafka09BinderTests.java
+++ b/spring-cloud-stream-binder-kafka-0.9-test/src/test/java/org/springframework/cloud/stream/binder/kafka/RawModeKafka09BinderTests.java
@@ -24,6 +24,8 @@ import org.springframework.cloud.stream.binder.Binding;
import org.springframework.cloud.stream.binder.ExtendedConsumerProperties;
import org.springframework.cloud.stream.binder.ExtendedProducerProperties;
import org.springframework.cloud.stream.binder.HeaderMode;
+import org.springframework.cloud.stream.binder.kafka.properties.KafkaConsumerProperties;
+import org.springframework.cloud.stream.binder.kafka.properties.KafkaProducerProperties;
import org.springframework.integration.IntegrationMessageHeaderAccessor;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.QueueChannel;
diff --git a/spring-cloud-stream-binder-kafka-core/pom.xml b/spring-cloud-stream-binder-kafka-core/pom.xml
new file mode 100644
index 000000000..dd863135a
--- /dev/null
+++ b/spring-cloud-stream-binder-kafka-core/pom.xml
@@ -0,0 +1,46 @@
+
+
+ 4.0.0
+
+ org.springframework.cloud
+ spring-cloud-stream-binder-kafka-parent
+ 1.2.0.BUILD-SNAPSHOT
+
+ spring-cloud-stream-binder-kafka-core
+ Spring Cloud Stream Kafka Binder Core
+ http://projects.spring.io/spring-cloud
+
+ Pivotal Software, Inc.
+ http://www.spring.io
+
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-stream
+
+
+ org.apache.kafka
+ kafka-clients
+
+
+ org.apache.kafka
+ kafka_2.11
+
+
+ org.springframework.integration
+ spring-integration-kafka
+ ${spring-integration-kafka.version}
+
+
+ org.apache.avro
+ avro-compiler
+
+
+
+
+
+
diff --git a/spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/admin/AdminUtilsOperation.java b/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/admin/AdminUtilsOperation.java
similarity index 100%
rename from spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/admin/AdminUtilsOperation.java
rename to spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/admin/AdminUtilsOperation.java
diff --git a/spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/admin/Kafka09AdminUtilsOperation.java b/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/admin/Kafka09AdminUtilsOperation.java
similarity index 99%
rename from spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/admin/Kafka09AdminUtilsOperation.java
rename to spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/admin/Kafka09AdminUtilsOperation.java
index dfacbf3bc..0723f1ed6 100644
--- a/spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/admin/Kafka09AdminUtilsOperation.java
+++ b/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/admin/Kafka09AdminUtilsOperation.java
@@ -142,4 +142,4 @@ public class Kafka09AdminUtilsOperation implements AdminUtilsOperation {
ReflectionUtils.handleReflectionException(e);
}
}
-}
+}
\ No newline at end of file
diff --git a/spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/admin/Kafka10AdminUtilsOperation.java b/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/admin/Kafka10AdminUtilsOperation.java
similarity index 100%
rename from spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/admin/Kafka10AdminUtilsOperation.java
rename to spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/admin/Kafka10AdminUtilsOperation.java
diff --git a/spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/config/JaasLoginModuleConfiguration.java b/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/properties/JaasLoginModuleConfiguration.java
similarity index 97%
rename from spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/config/JaasLoginModuleConfiguration.java
rename to spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/properties/JaasLoginModuleConfiguration.java
index fc2e97c21..33e9865f1 100644
--- a/spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/config/JaasLoginModuleConfiguration.java
+++ b/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/properties/JaasLoginModuleConfiguration.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.stream.binder.kafka.config;
+package org.springframework.cloud.stream.binder.kafka.properties;
import java.util.HashMap;
import java.util.Map;
diff --git a/spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/config/KafkaBinderConfigurationProperties.java b/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/properties/KafkaBinderConfigurationProperties.java
similarity index 98%
rename from spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/config/KafkaBinderConfigurationProperties.java
rename to spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/properties/KafkaBinderConfigurationProperties.java
index 158073a6d..4bb30d952 100644
--- a/spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/config/KafkaBinderConfigurationProperties.java
+++ b/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/properties/KafkaBinderConfigurationProperties.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.stream.binder.kafka.config;
+package org.springframework.cloud.stream.binder.kafka.properties;
import java.util.HashMap;
import java.util.Map;
diff --git a/spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/KafkaBindingProperties.java b/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/properties/KafkaBindingProperties.java
similarity index 94%
rename from spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/KafkaBindingProperties.java
rename to spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/properties/KafkaBindingProperties.java
index 6bd233d63..e7a5d731d 100644
--- a/spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/KafkaBindingProperties.java
+++ b/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/properties/KafkaBindingProperties.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.stream.binder.kafka;
+package org.springframework.cloud.stream.binder.kafka.properties;
/**
* @author Marius Bogoevici
diff --git a/spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/KafkaConsumerProperties.java b/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/properties/KafkaConsumerProperties.java
similarity index 97%
rename from spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/KafkaConsumerProperties.java
rename to spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/properties/KafkaConsumerProperties.java
index e824e356f..fec952db7 100644
--- a/spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/KafkaConsumerProperties.java
+++ b/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/properties/KafkaConsumerProperties.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.stream.binder.kafka;
+package org.springframework.cloud.stream.binder.kafka.properties;
import java.util.HashMap;
import java.util.Map;
diff --git a/spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/KafkaExtendedBindingProperties.java b/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/properties/KafkaExtendedBindingProperties.java
similarity index 96%
rename from spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/KafkaExtendedBindingProperties.java
rename to spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/properties/KafkaExtendedBindingProperties.java
index 25be14982..5b1cc9117 100644
--- a/spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/KafkaExtendedBindingProperties.java
+++ b/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/properties/KafkaExtendedBindingProperties.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.stream.binder.kafka;
+package org.springframework.cloud.stream.binder.kafka.properties;
import java.util.HashMap;
import java.util.Map;
diff --git a/spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/KafkaProducerProperties.java b/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/properties/KafkaProducerProperties.java
similarity index 96%
rename from spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/KafkaProducerProperties.java
rename to spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/properties/KafkaProducerProperties.java
index 2568a1c51..df0c78ebb 100644
--- a/spring-cloud-stream-binder-kafka/src/main/java/org/springframework/cloud/stream/binder/kafka/KafkaProducerProperties.java
+++ b/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/properties/KafkaProducerProperties.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.cloud.stream.binder.kafka;
+package org.springframework.cloud.stream.binder.kafka.properties;
import java.util.HashMap;
import java.util.Map;
diff --git a/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/provisioning/KafkaTopicProvisioner.java b/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/provisioning/KafkaTopicProvisioner.java
new file mode 100644
index 000000000..99c0b2fed
--- /dev/null
+++ b/spring-cloud-stream-binder-kafka-core/src/main/java/org/springframework/cloud/stream/binder/kafka/provisioning/KafkaTopicProvisioner.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright 2014-2016 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.provisioning;
+
+import java.util.Collection;
+import java.util.Properties;
+import java.util.concurrent.Callable;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.kafka.common.PartitionInfo;
+import org.apache.kafka.common.security.JaasUtils;
+
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.cloud.stream.binder.BinderException;
+import org.springframework.cloud.stream.binder.ExtendedConsumerProperties;
+import org.springframework.cloud.stream.binder.ExtendedProducerProperties;
+import org.springframework.cloud.stream.binder.kafka.admin.AdminUtilsOperation;
+import org.springframework.cloud.stream.binder.kafka.properties.KafkaBinderConfigurationProperties;
+import org.springframework.cloud.stream.binder.kafka.properties.KafkaConsumerProperties;
+import org.springframework.cloud.stream.binder.kafka.properties.KafkaProducerProperties;
+import org.springframework.cloud.stream.binder.kafka.utils.KafkaTopicUtils;
+import org.springframework.cloud.stream.provisioning.ConsumerDestination;
+import org.springframework.cloud.stream.provisioning.ProducerDestination;
+import org.springframework.cloud.stream.provisioning.ProvisioningException;
+import org.springframework.cloud.stream.provisioning.ProvisioningProvider;
+import org.springframework.retry.RetryCallback;
+import org.springframework.retry.RetryContext;
+import org.springframework.retry.RetryOperations;
+import org.springframework.retry.backoff.ExponentialBackOffPolicy;
+import org.springframework.retry.policy.SimpleRetryPolicy;
+import org.springframework.retry.support.RetryTemplate;
+import org.springframework.util.Assert;
+import org.springframework.util.StringUtils;
+
+import kafka.common.ErrorMapping;
+import kafka.utils.ZkUtils;
+
+/**
+ * Kafka implementation for {@link ProvisioningProvider}
+ *
+ * @author Soby Chacko
+ */
+public class KafkaTopicProvisioner implements ProvisioningProvider,
+ ExtendedProducerProperties>, InitializingBean {
+
+ private final Log logger = LogFactory.getLog(getClass());
+
+ private final KafkaBinderConfigurationProperties configurationProperties;
+
+ private final AdminUtilsOperation adminUtilsOperation;
+
+ private RetryOperations metadataRetryOperations;
+
+ public KafkaTopicProvisioner(KafkaBinderConfigurationProperties kafkaBinderConfigurationProperties,
+ AdminUtilsOperation adminUtilsOperation) {
+ this.configurationProperties = kafkaBinderConfigurationProperties;
+ this.adminUtilsOperation = adminUtilsOperation;
+ }
+
+ /**
+ *
+ * @param metadataRetryOperations the retry configuration
+ */
+ public void setMetadataRetryOperations(RetryOperations metadataRetryOperations) {
+ this.metadataRetryOperations = metadataRetryOperations;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ if (this.metadataRetryOperations == null) {
+ RetryTemplate retryTemplate = new RetryTemplate();
+
+ SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy();
+ simpleRetryPolicy.setMaxAttempts(10);
+ retryTemplate.setRetryPolicy(simpleRetryPolicy);
+
+ ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
+ backOffPolicy.setInitialInterval(100);
+ backOffPolicy.setMultiplier(2);
+ backOffPolicy.setMaxInterval(1000);
+ retryTemplate.setBackOffPolicy(backOffPolicy);
+ this.metadataRetryOperations = retryTemplate;
+ }
+ }
+
+ @Override
+ public ProducerDestination provisionProducerDestination(final String name, ExtendedProducerProperties properties) {
+ if (this.logger.isInfoEnabled()) {
+ this.logger.info("Using kafka topic for outbound: " + name);
+ }
+ KafkaTopicUtils.validateTopicName(name);
+ createTopicsIfAutoCreateEnabledAndAdminUtilsPresent(name, properties.getPartitionCount());
+ if (this.configurationProperties.isAutoCreateTopics() && adminUtilsOperation != null) {
+ final ZkUtils zkUtils = ZkUtils.apply(this.configurationProperties.getZkConnectionString(),
+ this.configurationProperties.getZkSessionTimeout(),
+ this.configurationProperties.getZkConnectionTimeout(),
+ JaasUtils.isZkSecurityEnabled());
+ int partitions = adminUtilsOperation.partitionSize(name, zkUtils);
+ return new KafkaProducerDestination(name, partitions);
+ }
+ else {
+ return new KafkaProducerDestination(name);
+ }
+ }
+
+ @Override
+ public ConsumerDestination provisionConsumerDestination(final String name, final String group, ExtendedConsumerProperties properties) {
+ KafkaTopicUtils.validateTopicName(name);
+ boolean anonymous = !StringUtils.hasText(group);
+ Assert.isTrue(!anonymous || !properties.getExtension().isEnableDlq(),
+ "DLQ support is not available for anonymous subscriptions");
+ if (properties.getInstanceCount() == 0) {
+ throw new IllegalArgumentException("Instance count cannot be zero");
+ }
+ int partitionCount = properties.getInstanceCount() * properties.getConcurrency();
+ createTopicsIfAutoCreateEnabledAndAdminUtilsPresent(name, partitionCount);
+ if (this.configurationProperties.isAutoCreateTopics() && adminUtilsOperation != null) {
+ final ZkUtils zkUtils = ZkUtils.apply(this.configurationProperties.getZkConnectionString(),
+ this.configurationProperties.getZkSessionTimeout(),
+ this.configurationProperties.getZkConnectionTimeout(),
+ JaasUtils.isZkSecurityEnabled());
+ int partitions = adminUtilsOperation.partitionSize(name, zkUtils);
+ if (properties.getExtension().isEnableDlq() && !anonymous) {
+ String dlqTopic = "error." + name + "." + group;
+ createTopicAndPartitions(dlqTopic, partitions);
+ return new KafkaConsumerDestination(name, partitions, dlqTopic);
+ }
+ return new KafkaConsumerDestination(name, partitions);
+ }
+ return new KafkaConsumerDestination(name);
+ }
+
+ private void createTopicsIfAutoCreateEnabledAndAdminUtilsPresent(final String topicName, final int partitionCount) {
+ if (this.configurationProperties.isAutoCreateTopics() && adminUtilsOperation != null) {
+ createTopicAndPartitions(topicName, partitionCount);
+ }
+ else if (this.configurationProperties.isAutoCreateTopics() && adminUtilsOperation == null) {
+ this.logger.warn("Auto creation of topics is enabled, but Kafka AdminUtils class is not present on the classpath. " +
+ "No topic will be created by the binder");
+ }
+ else if (!this.configurationProperties.isAutoCreateTopics()) {
+ this.logger.info("Auto creation of topics is disabled.");
+ }
+ }
+
+ /**
+ * Creates a Kafka topic if needed, or try to increase its partition count to the
+ * desired number.
+ */
+ private void createTopicAndPartitions(final String topicName, final int partitionCount) {
+ final ZkUtils zkUtils = ZkUtils.apply(this.configurationProperties.getZkConnectionString(),
+ this.configurationProperties.getZkSessionTimeout(),
+ this.configurationProperties.getZkConnectionTimeout(),
+ JaasUtils.isZkSecurityEnabled());
+ try {
+ short errorCode = adminUtilsOperation.errorCodeFromTopicMetadata(topicName, zkUtils);
+ if (errorCode == ErrorMapping.NoError()) {
+ // only consider minPartitionCount for resizing if autoAddPartitions is true
+ int effectivePartitionCount = this.configurationProperties.isAutoAddPartitions()
+ ? Math.max(this.configurationProperties.getMinPartitionCount(), partitionCount)
+ : partitionCount;
+ int partitionSize = adminUtilsOperation.partitionSize(topicName, zkUtils);
+
+ if (partitionSize < effectivePartitionCount) {
+ if (this.configurationProperties.isAutoAddPartitions()) {
+ adminUtilsOperation.invokeAddPartitions(zkUtils, topicName, effectivePartitionCount, null, false);
+ }
+ else {
+ throw new ProvisioningException("The number of expected partitions was: " + partitionCount + ", but "
+ + partitionSize + (partitionSize > 1 ? " have " : " has ") + "been found instead."
+ + "Consider either increasing the partition count of the topic or enabling " +
+ "`autoAddPartitions`");
+ }
+ }
+ }
+ else if (errorCode == ErrorMapping.UnknownTopicOrPartitionCode()) {
+ // always consider minPartitionCount for topic creation
+ final int effectivePartitionCount = Math.max(this.configurationProperties.getMinPartitionCount(),
+ partitionCount);
+
+ this.metadataRetryOperations.execute(new RetryCallback