GH-204: DSL Register container as bean if needed
Fixes https://github.com/spring-projects/spring-integration-kafka/issues/204 When an external container is provided to the DSL, register it as a bean if it is not already a bean. Polishing id from PR comments; add gateway support too. * Polishing JavaDocs and omissions in the test-case
This commit is contained in:
committed by
Artem Bilan
parent
e296d66a4b
commit
8decbe7810
@@ -104,7 +104,11 @@ public final class Kafka {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an initial {@link KafkaMessageDrivenChannelAdapterSpec}.
|
||||
* Create an initial {@link KafkaMessageDrivenChannelAdapterSpec}. If the listener
|
||||
* container is not already a bean it will be registered in the application context.
|
||||
* If the adapter spec has an {@code id}, the bean name will be that id appended with
|
||||
* '.container'. Otherwise, the bean name will be generated from the container class
|
||||
* name.
|
||||
* @param listenerContainer the {@link AbstractMessageListenerContainer}.
|
||||
* @param <K> the Kafka message key type.
|
||||
* @param <V> the Kafka message value type.
|
||||
@@ -117,7 +121,11 @@ public final class Kafka {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an initial {@link KafkaMessageDrivenChannelAdapterSpec}.
|
||||
* Create an initial {@link KafkaMessageDrivenChannelAdapterSpec}. If the listener
|
||||
* container is not already a bean it will be registered in the application context.
|
||||
* If the adapter spec has an {@code id}, the bean name will be that id appended with
|
||||
* '.container'. Otherwise, the bean name will be generated from the container class
|
||||
* name.
|
||||
* @param listenerContainer the {@link AbstractMessageListenerContainer}.
|
||||
* @param listenerMode the {@link KafkaMessageDrivenChannelAdapter.ListenerMode}.
|
||||
* @param <K> the Kafka message key type.
|
||||
@@ -316,7 +324,10 @@ public final class Kafka {
|
||||
|
||||
/**
|
||||
* Create an initial {@link KafkaInboundGatewaySpec} with the provided container and
|
||||
* template.
|
||||
* template. If the listener container is not already a bean it will be registered in
|
||||
* the application context. If the adapter spec has an {@code id}, the bean name will
|
||||
* be that id appended with '.container'. Otherwise, the bean name will be generated
|
||||
* from the container class name.
|
||||
* @param container the container.
|
||||
* @param template the template.
|
||||
* @param <K> the Kafka message key type.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.integration.kafka.dsl;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -44,12 +45,16 @@ import org.springframework.util.Assert;
|
||||
* @since 3.0.2
|
||||
*/
|
||||
public class KafkaInboundGatewaySpec<K, V, R, S extends KafkaInboundGatewaySpec<K, V, R, S>>
|
||||
extends MessagingGatewaySpec<S, KafkaInboundGateway<K, V, R>> {
|
||||
extends MessagingGatewaySpec<S, KafkaInboundGateway<K, V, R>>
|
||||
implements ComponentsRegistration {
|
||||
|
||||
private final AbstractMessageListenerContainer<K, V> container;
|
||||
|
||||
KafkaInboundGatewaySpec(AbstractMessageListenerContainer<K, V> messageListenerContainer,
|
||||
KafkaTemplate<K, R> kafkaTemplate) {
|
||||
|
||||
super(new KafkaInboundGateway<>(messageListenerContainer, kafkaTemplate));
|
||||
this.container = messageListenerContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,6 +91,11 @@ public class KafkaInboundGatewaySpec<K, V, R, S extends KafkaInboundGatewaySpec<
|
||||
return _this();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Object, String> getComponentsToRegister() {
|
||||
return Collections.singletonMap(this.container, getId() == null ? null : getId() + ".container");
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link ConcurrentMessageListenerContainer} configuration {@link KafkaInboundGatewaySpec}
|
||||
* extension.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2016-2018 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.
|
||||
@@ -46,11 +46,15 @@ import org.springframework.util.Assert;
|
||||
* @since 3.0
|
||||
*/
|
||||
public class KafkaMessageDrivenChannelAdapterSpec<K, V, S extends KafkaMessageDrivenChannelAdapterSpec<K, V, S>>
|
||||
extends MessageProducerSpec<S, KafkaMessageDrivenChannelAdapter<K, V>> {
|
||||
extends MessageProducerSpec<S, KafkaMessageDrivenChannelAdapter<K, V>>
|
||||
implements ComponentsRegistration {
|
||||
|
||||
private final AbstractMessageListenerContainer<K, V> container;
|
||||
|
||||
KafkaMessageDrivenChannelAdapterSpec(AbstractMessageListenerContainer<K, V> messageListenerContainer,
|
||||
KafkaMessageDrivenChannelAdapter.ListenerMode listenerMode) {
|
||||
super(new KafkaMessageDrivenChannelAdapter<>(messageListenerContainer, listenerMode));
|
||||
this.container = messageListenerContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,6 +156,11 @@ public class KafkaMessageDrivenChannelAdapterSpec<K, V, S extends KafkaMessageDr
|
||||
return _this();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Object, String> getComponentsToRegister() {
|
||||
return Collections.singletonMap(this.container, getId() == null ? null : getId() + ".container");
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link ConcurrentMessageListenerContainer} configuration {@link KafkaMessageDrivenChannelAdapterSpec}
|
||||
* extension.
|
||||
|
||||
@@ -52,12 +52,14 @@ import org.springframework.integration.kafka.support.RawRecordHeaderErrorMessage
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.kafka.annotation.EnableKafka;
|
||||
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
|
||||
import org.springframework.kafka.core.ConsumerFactory;
|
||||
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
|
||||
import org.springframework.kafka.core.DefaultKafkaProducerFactory;
|
||||
import org.springframework.kafka.core.KafkaTemplate;
|
||||
import org.springframework.kafka.core.ProducerFactory;
|
||||
import org.springframework.kafka.listener.ContainerProperties;
|
||||
import org.springframework.kafka.listener.ContainerProperties.AckMode;
|
||||
import org.springframework.kafka.listener.GenericMessageListenerContainer;
|
||||
import org.springframework.kafka.listener.KafkaMessageListenerContainer;
|
||||
import org.springframework.kafka.listener.MessageListenerContainer;
|
||||
@@ -100,8 +102,8 @@ public class KafkaDslTests {
|
||||
private static final String TEST_TOPIC5 = "test-topic5";
|
||||
|
||||
@ClassRule
|
||||
public static KafkaEmbedded embeddedKafka = new KafkaEmbedded(1, true, TEST_TOPIC1, TEST_TOPIC2, TEST_TOPIC3,
|
||||
TEST_TOPIC4, TEST_TOPIC5);
|
||||
public static KafkaEmbedded embeddedKafka =
|
||||
new KafkaEmbedded(1, true, TEST_TOPIC1, TEST_TOPIC2, TEST_TOPIC3, TEST_TOPIC4, TEST_TOPIC5);
|
||||
|
||||
@Autowired
|
||||
@Qualifier("sendToKafkaFlow.input")
|
||||
@@ -212,7 +214,7 @@ public class KafkaDslTests {
|
||||
|
||||
@Test
|
||||
public void testGateways() throws Exception {
|
||||
assertThat(this.config.replyContainerLatch.await(30, TimeUnit.SECONDS));
|
||||
assertThat(this.config.replyContainerLatch.await(30, TimeUnit.SECONDS)).isTrue();
|
||||
assertThat(this.gate.exchange(TEST_TOPIC4, "foo")).isEqualTo("FOO");
|
||||
}
|
||||
|
||||
@@ -259,16 +261,23 @@ public class KafkaDslTests {
|
||||
.get();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConcurrentKafkaListenerContainerFactory<Integer, String> kafkaListenerContainerFactory() {
|
||||
ConcurrentKafkaListenerContainerFactory<Integer, String> factory =
|
||||
new ConcurrentKafkaListenerContainerFactory<>();
|
||||
factory.setConsumerFactory(consumerFactory());
|
||||
factory.getContainerProperties().setAckMode(AckMode.MANUAL);
|
||||
factory.setRecoveryCallback(new ErrorMessageSendingRecoverer(errorChannel(),
|
||||
new RawRecordHeaderErrorMessageStrategy()));
|
||||
factory.setRetryTemplate(new RetryTemplate());
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow topic2ListenerFromKafkaFlow() {
|
||||
return IntegrationFlows
|
||||
.from(Kafka.messageDrivenChannelAdapter(consumerFactory(),
|
||||
KafkaMessageDrivenChannelAdapter.ListenerMode.record, TEST_TOPIC2)
|
||||
.configureListenerContainer(c ->
|
||||
c.ackMode(ContainerProperties.AckMode.MANUAL))
|
||||
.recoveryCallback(new ErrorMessageSendingRecoverer(errorChannel(),
|
||||
new RawRecordHeaderErrorMessageStrategy()))
|
||||
.retryTemplate(new RetryTemplate())
|
||||
.from(Kafka.messageDrivenChannelAdapter(kafkaListenerContainerFactory().createContainer(TEST_TOPIC2),
|
||||
KafkaMessageDrivenChannelAdapter.ListenerMode.record)
|
||||
.filterInRetry(true))
|
||||
.filter(Message.class, m ->
|
||||
m.getHeaders().get(KafkaHeaders.RECEIVED_MESSAGE_KEY, Integer.class) < 101,
|
||||
@@ -380,4 +389,5 @@ public class KafkaDslTests {
|
||||
String exchange(@Header(KafkaHeaders.TOPIC) String topic, String out);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user