Renamed MessageBus to Binder
- Renamed MessageBus to Binder - Parameterized Binder interface - Restored exclusion of spring-xd-codec
This commit is contained in:
committed by
Marius Bogoevici
parent
11e9f269db
commit
35b74b00b3
9
pom.xml
9
pom.xml
@@ -27,9 +27,8 @@
|
||||
</properties>
|
||||
<modules>
|
||||
<module>spring-cloud-stream</module>
|
||||
<module>spring-cloud-stream-bindings</module>
|
||||
<module>spring-cloud-stream-binders</module>
|
||||
<module>spring-cloud-stream-codec</module>
|
||||
<module>spring-cloud-stream-common</module>
|
||||
<module>spring-cloud-stream-samples</module>
|
||||
<module>docs</module>
|
||||
</modules>
|
||||
@@ -76,17 +75,17 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-local</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-local</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-redis</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-redis</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-rabbit</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-cloud-stream-bindings-parent</artifactId>
|
||||
<artifactId>spring-cloud-stream-binders-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<url>http://projects.spring.io/spring-xd/</url>
|
||||
<organization>
|
||||
@@ -20,24 +20,24 @@
|
||||
<curator.version>2.6.0</curator.version>
|
||||
</properties>
|
||||
<modules>
|
||||
<module>spring-cloud-stream-binding-spi</module>
|
||||
<module>spring-cloud-stream-binding-test</module>
|
||||
<module>spring-cloud-stream-binding-local</module>
|
||||
<module>spring-cloud-stream-binding-rabbit</module>
|
||||
<module>spring-cloud-stream-binding-redis</module>
|
||||
<module>spring-cloud-stream-binding-kafka</module>
|
||||
<module>spring-cloud-stream-binder-spi</module>
|
||||
<module>spring-cloud-stream-binder-test</module>
|
||||
<module>spring-cloud-stream-binder-local</module>
|
||||
<module>spring-cloud-stream-binder-rabbit</module>
|
||||
<module>spring-cloud-stream-binder-redis</module>
|
||||
<module>spring-cloud-stream-binder-kafka</module>
|
||||
</modules>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-spi</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-spi</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-test</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-test</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
@@ -3,14 +3,14 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-cloud-stream-binding-kafka</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-kafka</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>spring-cloud-stream-binding-kafka</name>
|
||||
<description>Kafka binding implementation</description>
|
||||
<name>spring-cloud-stream-binder-kafka</name>
|
||||
<description>Kafka binder implementation</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-bindings-parent</artifactId>
|
||||
<artifactId>spring-cloud-stream-binders-parent</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-spi</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-test</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-test</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
@@ -43,6 +43,8 @@ import org.apache.kafka.clients.producer.ProducerConfig;
|
||||
import org.apache.kafka.common.serialization.ByteArraySerializer;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.cloud.stream.binder.BinderException;
|
||||
import org.springframework.cloud.stream.binder.BinderHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.integration.channel.FixedSubscriberChannel;
|
||||
import org.springframework.integration.endpoint.EventDrivenConsumer;
|
||||
@@ -77,21 +79,20 @@ import org.springframework.retry.support.RetryTemplate;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.xd.dirt.integration.bus.AbstractBusPropertiesAccessor;
|
||||
import org.springframework.xd.dirt.integration.bus.Binding;
|
||||
import org.springframework.xd.dirt.integration.bus.BusProperties;
|
||||
import org.springframework.xd.dirt.integration.bus.EmbeddedHeadersMessageConverter;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageBusSupport;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageValues;
|
||||
import org.springframework.xd.dirt.integration.bus.XdHeaders;
|
||||
import org.springframework.cloud.stream.binder.AbstractBinderPropertiesAccessor;
|
||||
import org.springframework.cloud.stream.binder.Binding;
|
||||
import org.springframework.cloud.stream.binder.BinderProperties;
|
||||
import org.springframework.cloud.stream.binder.EmbeddedHeadersMessageConverter;
|
||||
import org.springframework.cloud.stream.binder.MessageChannelBinderSupport;
|
||||
import org.springframework.cloud.stream.binder.MessageValues;
|
||||
import org.springframework.xd.dirt.integration.bus.serializer.MultiTypeCodec;
|
||||
|
||||
import scala.collection.Seq;
|
||||
|
||||
/**
|
||||
* A message bus that uses Kafka as the underlying middleware. The general implementation mapping between XD concepts
|
||||
* A binder that uses Kafka as the underlying middleware. The general implementation mapping between XD concepts
|
||||
* and Kafka concepts is as follows:
|
||||
* A message bus that uses Kafka as the underlying middleware.
|
||||
* A binder that uses Kafka as the underlying middleware.
|
||||
* The general implementation mapping between XD concepts and Kafka concepts is as follows:
|
||||
* <table>
|
||||
* <tr>
|
||||
@@ -124,7 +125,7 @@ import scala.collection.Seq;
|
||||
* @author David Turanski
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public class KafkaMessageBus extends MessageBusSupport {
|
||||
public class KafkaMessageChannelBinder extends MessageChannelBinderSupport {
|
||||
|
||||
public static final ByteArraySerializer BYTE_ARRAY_SERIALIZER = new ByteArraySerializer();
|
||||
|
||||
@@ -182,7 +183,7 @@ public class KafkaMessageBus extends MessageBusSupport {
|
||||
|
||||
protected static final Set<Object> PRODUCER_COMPRESSION_PROPERTIES = new HashSet<Object>(
|
||||
Arrays.asList(new String[] {
|
||||
KafkaMessageBus.COMPRESSION_CODEC,
|
||||
KafkaMessageChannelBinder.COMPRESSION_CODEC,
|
||||
}));
|
||||
|
||||
/**
|
||||
@@ -192,7 +193,7 @@ public class KafkaMessageBus extends MessageBusSupport {
|
||||
private static final String POINT_TO_POINT_SEMANTICS_CONSUMER_GROUP = "springXD";
|
||||
|
||||
private static final Set<Object> KAFKA_CONSUMER_PROPERTIES = new SetBuilder()
|
||||
.add(BusProperties.MIN_PARTITION_COUNT)
|
||||
.add(BinderProperties.MIN_PARTITION_COUNT)
|
||||
.build();
|
||||
|
||||
/**
|
||||
@@ -201,14 +202,14 @@ public class KafkaMessageBus extends MessageBusSupport {
|
||||
private static final Set<Object> SUPPORTED_CONSUMER_PROPERTIES = new SetBuilder()
|
||||
.addAll(CONSUMER_STANDARD_PROPERTIES)
|
||||
.addAll(KAFKA_CONSUMER_PROPERTIES)
|
||||
.add(BusProperties.PARTITION_INDEX) // Not actually used
|
||||
.add(BusProperties.COUNT) // Not actually used
|
||||
.add(BusProperties.CONCURRENCY)
|
||||
.add(BinderProperties.PARTITION_INDEX) // Not actually used
|
||||
.add(BinderProperties.COUNT) // Not actually used
|
||||
.add(BinderProperties.CONCURRENCY)
|
||||
.add(FETCH_SIZE)
|
||||
.build();
|
||||
|
||||
private static final Set<Object> KAFKA_PRODUCER_PROPERTIES = new SetBuilder()
|
||||
.add(BusProperties.MIN_PARTITION_COUNT)
|
||||
.add(BinderProperties.MIN_PARTITION_COUNT)
|
||||
.build();
|
||||
|
||||
/**
|
||||
@@ -229,7 +230,7 @@ public class KafkaMessageBus extends MessageBusSupport {
|
||||
private static final Set<Object> SUPPORTED_PRODUCER_PROPERTIES = new SetBuilder()
|
||||
.addAll(PRODUCER_PARTITIONING_PROPERTIES)
|
||||
.addAll(PRODUCER_STANDARD_PROPERTIES)
|
||||
.add(BusProperties.DIRECT_BINDING_ALLOWED)
|
||||
.add(BinderProperties.DIRECT_BINDING_ALLOWED)
|
||||
.addAll(KAFKA_PRODUCER_PROPERTIES)
|
||||
.addAll(PRODUCER_BATCHING_BASIC_PROPERTIES)
|
||||
.addAll(PRODUCER_COMPRESSION_PROPERTIES)
|
||||
@@ -291,7 +292,7 @@ public class KafkaMessageBus extends MessageBusSupport {
|
||||
|
||||
private Mode mode = Mode.embeddedHeaders;
|
||||
|
||||
public KafkaMessageBus(ZookeeperConnect zookeeperConnect, String brokers, String zkAddress,
|
||||
public KafkaMessageChannelBinder(ZookeeperConnect zookeeperConnect, String brokers, String zkAddress,
|
||||
MultiTypeCodec<Object> codec, String... headersToMap) {
|
||||
this.zookeeperConnect = zookeeperConnect;
|
||||
this.brokers = brokers;
|
||||
@@ -299,14 +300,14 @@ public class KafkaMessageBus extends MessageBusSupport {
|
||||
setCodec(codec);
|
||||
if (headersToMap.length > 0) {
|
||||
String[] combinedHeadersToMap =
|
||||
Arrays.copyOfRange(XdHeaders.STANDARD_HEADERS, 0, XdHeaders.STANDARD_HEADERS.length + headersToMap
|
||||
Arrays.copyOfRange(BinderHeaders.STANDARD_HEADERS, 0, BinderHeaders.STANDARD_HEADERS.length + headersToMap
|
||||
.length);
|
||||
System.arraycopy(headersToMap, 0, combinedHeadersToMap, XdHeaders.STANDARD_HEADERS.length, headersToMap
|
||||
System.arraycopy(headersToMap, 0, combinedHeadersToMap, BinderHeaders.STANDARD_HEADERS.length, headersToMap
|
||||
.length);
|
||||
this.headersToMap = combinedHeadersToMap;
|
||||
}
|
||||
else {
|
||||
this.headersToMap = XdHeaders.STANDARD_HEADERS;
|
||||
this.headersToMap = BinderHeaders.STANDARD_HEADERS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -546,12 +547,12 @@ public class KafkaMessageBus extends MessageBusSupport {
|
||||
|
||||
@Override
|
||||
public void bindRequestor(String name, MessageChannel requests, MessageChannel replies, Properties properties) {
|
||||
throw new UnsupportedOperationException("requestor binding is not supported by this bus");
|
||||
throw new UnsupportedOperationException("requestor binding is not supported by this binder");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindReplier(String name, MessageChannel requests, MessageChannel replies, Properties properties) {
|
||||
throw new UnsupportedOperationException("replier binding is not supported by this bus");
|
||||
throw new UnsupportedOperationException("replier binding is not supported by this binder");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -599,8 +600,8 @@ public class KafkaMessageBus extends MessageBusSupport {
|
||||
return partitions;
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.error("Cannot initialize MessageBus", e);
|
||||
throw new RuntimeException("Cannot initialize message bus:", e);
|
||||
logger.error("Cannot initialize Binder", e);
|
||||
throw new BinderException("Cannot initialize binder:", e);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -786,7 +787,7 @@ public class KafkaMessageBus extends MessageBusSupport {
|
||||
}
|
||||
}
|
||||
|
||||
private class KafkaPropertiesAccessor extends AbstractBusPropertiesAccessor {
|
||||
private class KafkaPropertiesAccessor extends AbstractBinderPropertiesAccessor {
|
||||
|
||||
public KafkaPropertiesAccessor(Properties properties) {
|
||||
super(properties);
|
||||
@@ -833,7 +834,7 @@ public class KafkaMessageBus extends MessageBusSupport {
|
||||
private class ReceivingHandler extends AbstractReplyProducingMessageHandler {
|
||||
|
||||
public ReceivingHandler() {
|
||||
this.setBeanFactory(KafkaMessageBus.this.getBeanFactory());
|
||||
this.setBeanFactory(KafkaMessageChannelBinder.this.getBeanFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -850,7 +851,7 @@ public class KafkaMessageBus extends MessageBusSupport {
|
||||
messageValues = new MessageValues(requestMessage);
|
||||
}
|
||||
messageValues = deserializePayloadIfNecessary(messageValues);
|
||||
return MessageBuilder.createMessage(messageValues.getPayload(), new KafkaBusMessageHeaders(
|
||||
return MessageBuilder.createMessage(messageValues.getPayload(), new KafkaBinderHeaders(
|
||||
messageValues));
|
||||
}
|
||||
else {
|
||||
@@ -859,9 +860,9 @@ public class KafkaMessageBus extends MessageBusSupport {
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private final class KafkaBusMessageHeaders extends MessageHeaders {
|
||||
private final class KafkaBinderHeaders extends MessageHeaders {
|
||||
|
||||
KafkaBusMessageHeaders(Map<String, Object> headers) {
|
||||
KafkaBinderHeaders(Map<String, Object> headers) {
|
||||
super(headers, MessageHeaders.ID_VALUE_NONE, -1L);
|
||||
}
|
||||
}
|
||||
@@ -892,7 +893,7 @@ public class KafkaMessageBus extends MessageBusSupport {
|
||||
this.topicName = topicName;
|
||||
this.numberOfKafkaPartitions = numberOfPartitions;
|
||||
this.partitioningMetadata = new PartitioningMetadata(properties, numberOfPartitions);
|
||||
this.setBeanFactory(KafkaMessageBus.this.getBeanFactory());
|
||||
this.setBeanFactory(KafkaMessageChannelBinder.this.getBeanFactory());
|
||||
this.producerConfiguration = producerConfiguration;
|
||||
}
|
||||
|
||||
@@ -909,7 +910,7 @@ public class KafkaMessageBus extends MessageBusSupport {
|
||||
if (Mode.embeddedHeaders.equals(mode)) {
|
||||
MessageValues transformed = serializePayloadIfNecessary(message);
|
||||
byte[] messageToSend = embeddedHeadersMessageConverter.embedHeaders(transformed,
|
||||
KafkaMessageBus.this.headersToMap);
|
||||
KafkaMessageChannelBinder.this.headersToMap);
|
||||
producerConfiguration.send(topicName, targetPartition, null, messageToSend);
|
||||
}
|
||||
else if (Mode.raw.equals(mode)) {
|
||||
@@ -11,7 +11,7 @@
|
||||
</bean>
|
||||
|
||||
|
||||
<bean id="messageBus" class="org.springframework.xd.dirt.integration.kafka.KafkaMessageBus">
|
||||
<bean id="messageBus" class="org.springframework.xd.dirt.integration.kafka.KafkaMessageChannelBinder">
|
||||
<constructor-arg ref="zookeeperConnect"/>
|
||||
<constructor-arg value="${xd.messagebus.kafka.brokers}"/>
|
||||
<constructor-arg value="${xd.messagebus.kafka.zkAddress}"/>
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
|
||||
package org.springframework.xd.dirt.integration.kafka;
|
||||
package org.springframework.cloud.stream.binder.kafka;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus.kafka;
|
||||
package org.springframework.cloud.stream.binder.kafka;
|
||||
|
||||
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
@@ -35,6 +35,7 @@ import org.junit.ClassRule;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.cloud.stream.binder.PartitionCapableBinderTests;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.kafka.core.KafkaMessage;
|
||||
@@ -42,42 +43,42 @@ import org.springframework.integration.kafka.core.Partition;
|
||||
import org.springframework.integration.kafka.listener.KafkaMessageListenerContainer;
|
||||
import org.springframework.integration.kafka.listener.MessageListener;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.xd.dirt.integration.bus.BusProperties;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageBus;
|
||||
import org.springframework.xd.dirt.integration.bus.PartitionCapableBusTests;
|
||||
import org.springframework.xd.dirt.integration.bus.Spy;
|
||||
import org.springframework.xd.dirt.integration.kafka.KafkaMessageBus;
|
||||
import org.springframework.xd.dirt.integration.kafka.KafkaTestSupport;
|
||||
import org.springframework.cloud.stream.binder.BinderProperties;
|
||||
import org.springframework.cloud.stream.binder.Binder;
|
||||
import org.springframework.cloud.stream.binder.Spy;
|
||||
import org.springframework.xd.dirt.integration.kafka.KafkaMessageChannelBinder;
|
||||
|
||||
|
||||
/**
|
||||
* Integration tests for the {@link KafkaMessageBus}.
|
||||
* Integration tests for the {@link org.springframework.xd.dirt.integration.kafka.KafkaMessageChannelBinder}.
|
||||
*
|
||||
* @author Eric Bottard
|
||||
* @author Marius Bogoevici
|
||||
*/
|
||||
public class KafkaMessageBusTests extends PartitionCapableBusTests {
|
||||
public class KafkaBinderTests extends PartitionCapableBinderTests {
|
||||
|
||||
private final String CLASS_UNDER_TEST_NAME = KafkaMessageChannelBinder.class.getSimpleName();
|
||||
|
||||
@ClassRule
|
||||
public static KafkaTestSupport kafkaTestSupport = new KafkaTestSupport();
|
||||
|
||||
private KafkaTestMessageBus messageBus;
|
||||
private KafkaTestBinder binder;
|
||||
|
||||
@Override
|
||||
protected void busBindUnbindLatency() throws InterruptedException {
|
||||
protected void binderBindUnbindLatency() throws InterruptedException {
|
||||
Thread.sleep(500);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MessageBus getMessageBus() {
|
||||
if (messageBus == null) {
|
||||
messageBus = createKafkaTestMessageBus();
|
||||
protected Binder getBinder() {
|
||||
if (binder == null) {
|
||||
binder = createKafkaTestBinder();
|
||||
}
|
||||
return messageBus;
|
||||
return binder;
|
||||
}
|
||||
|
||||
protected KafkaTestMessageBus createKafkaTestMessageBus() {
|
||||
return new KafkaTestMessageBus(kafkaTestSupport, getCodec(), KafkaMessageBus.Mode.embeddedHeaders);
|
||||
protected KafkaTestBinder createKafkaTestBinder() {
|
||||
return new KafkaTestBinder(kafkaTestSupport, getCodec(), KafkaMessageChannelBinder.Mode.embeddedHeaders);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,13 +87,18 @@ public class KafkaMessageBusTests extends PartitionCapableBusTests {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spy spyOn(final String name) {
|
||||
String topic = KafkaMessageBus.escapeTopicName(name);
|
||||
protected String getClassUnderTestName() {
|
||||
return CLASS_UNDER_TEST_NAME;
|
||||
}
|
||||
|
||||
KafkaTestMessageBus busWrapper = (KafkaTestMessageBus) getMessageBus();
|
||||
@Override
|
||||
public Spy spyOn(final String name) {
|
||||
String topic = KafkaMessageChannelBinder.escapeTopicName(name);
|
||||
|
||||
KafkaTestBinder binderWrapper = (KafkaTestBinder) getBinder();
|
||||
// Rewind offset, as tests will have typically already sent the messages we're trying to consume
|
||||
|
||||
KafkaMessageListenerContainer messageListenerContainer = busWrapper.getCoreMessageBus().createMessageListenerContainer(
|
||||
KafkaMessageListenerContainer messageListenerContainer = binderWrapper.getCoreBinder().createMessageListenerContainer(
|
||||
new Properties(), UUID.randomUUID().toString(), 1, topic, OffsetRequest.EarliestTime());
|
||||
|
||||
final BlockingQueue<KafkaMessage> messages = new ArrayBlockingQueue<KafkaMessage>(10);
|
||||
@@ -122,26 +128,26 @@ public class KafkaMessageBusTests extends PartitionCapableBusTests {
|
||||
|
||||
byte[] ratherBigPayload = new byte[2048];
|
||||
Arrays.fill(ratherBigPayload, (byte) 65);
|
||||
MessageBus messageBus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
|
||||
for (String codec : codecs) {
|
||||
DirectChannel moduleOutputChannel = new DirectChannel();
|
||||
QueueChannel moduleInputChannel = new QueueChannel();
|
||||
Properties props = new Properties();
|
||||
if (codec != null) {
|
||||
props.put(KafkaMessageBus.COMPRESSION_CODEC, codec);
|
||||
props.put(KafkaMessageChannelBinder.COMPRESSION_CODEC, codec);
|
||||
}
|
||||
messageBus.bindProducer("foo.0", moduleOutputChannel, props);
|
||||
messageBus.bindConsumer("foo.0", moduleInputChannel, null);
|
||||
binder.bindProducer("foo.0", moduleOutputChannel, props);
|
||||
binder.bindConsumer("foo.0", moduleInputChannel, null);
|
||||
Message<?> message = org.springframework.integration.support.MessageBuilder.withPayload(ratherBigPayload).build();
|
||||
// Let the consumer actually bind to the producer before sending a msg
|
||||
busBindUnbindLatency();
|
||||
binderBindUnbindLatency();
|
||||
moduleOutputChannel.send(message);
|
||||
Message<?> inbound = moduleInputChannel.receive(2000);
|
||||
assertNotNull(inbound);
|
||||
assertArrayEquals(ratherBigPayload, (byte[]) inbound.getPayload());
|
||||
messageBus.unbindProducers("foo.0");
|
||||
messageBus.unbindConsumers("foo.0");
|
||||
binder.unbindProducers("foo.0");
|
||||
binder.unbindConsumers("foo.0");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,30 +156,30 @@ public class KafkaMessageBusTests extends PartitionCapableBusTests {
|
||||
|
||||
byte[] ratherBigPayload = new byte[2048];
|
||||
Arrays.fill(ratherBigPayload, (byte) 65);
|
||||
KafkaTestMessageBus messageBus = (KafkaTestMessageBus) getMessageBus();
|
||||
KafkaTestBinder binder = (KafkaTestBinder) getBinder();
|
||||
|
||||
|
||||
DirectChannel moduleOutputChannel = new DirectChannel();
|
||||
QueueChannel moduleInputChannel = new QueueChannel();
|
||||
Properties producerProperties = new Properties();
|
||||
producerProperties.put(BusProperties.MIN_PARTITION_COUNT, "10");
|
||||
producerProperties.put(BinderProperties.MIN_PARTITION_COUNT, "10");
|
||||
Properties consumerProperties = new Properties();
|
||||
consumerProperties.put(BusProperties.MIN_PARTITION_COUNT, "10");
|
||||
consumerProperties.put(BinderProperties.MIN_PARTITION_COUNT, "10");
|
||||
long uniqueBindingId = System.currentTimeMillis();
|
||||
messageBus.bindProducer("foo" + uniqueBindingId + ".0", moduleOutputChannel, producerProperties);
|
||||
messageBus.bindConsumer("foo" + uniqueBindingId + ".0", moduleInputChannel, consumerProperties);
|
||||
binder.bindProducer("foo" + uniqueBindingId + ".0", moduleOutputChannel, producerProperties);
|
||||
binder.bindConsumer("foo" + uniqueBindingId + ".0", moduleInputChannel, consumerProperties);
|
||||
Message<?> message = org.springframework.integration.support.MessageBuilder.withPayload(ratherBigPayload).build();
|
||||
// Let the consumer actually bind to the producer before sending a msg
|
||||
busBindUnbindLatency();
|
||||
binderBindUnbindLatency();
|
||||
moduleOutputChannel.send(message);
|
||||
Message<?> inbound = moduleInputChannel.receive(2000);
|
||||
assertNotNull(inbound);
|
||||
assertArrayEquals(ratherBigPayload, (byte[]) inbound.getPayload());
|
||||
Collection<Partition> partitions = messageBus.getCoreMessageBus().getConnectionFactory().getPartitions(
|
||||
Collection<Partition> partitions = binder.getCoreBinder().getConnectionFactory().getPartitions(
|
||||
"foo" + uniqueBindingId + ".0");
|
||||
assertThat(partitions, hasSize(10));
|
||||
messageBus.unbindProducers("foo" + uniqueBindingId + ".0");
|
||||
messageBus.unbindConsumers("foo" + uniqueBindingId + ".0");
|
||||
binder.unbindProducers("foo" + uniqueBindingId + ".0");
|
||||
binder.unbindConsumers("foo" + uniqueBindingId + ".0");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -181,32 +187,32 @@ public class KafkaMessageBusTests extends PartitionCapableBusTests {
|
||||
|
||||
byte[] ratherBigPayload = new byte[2048];
|
||||
Arrays.fill(ratherBigPayload, (byte) 65);
|
||||
KafkaTestMessageBus messageBus = (KafkaTestMessageBus) getMessageBus();
|
||||
KafkaTestBinder binder = (KafkaTestBinder) getBinder();
|
||||
|
||||
|
||||
DirectChannel moduleOutputChannel = new DirectChannel();
|
||||
QueueChannel moduleInputChannel = new QueueChannel();
|
||||
Properties producerProps = new Properties();
|
||||
producerProps.put(BusProperties.MIN_PARTITION_COUNT, "5");
|
||||
producerProps.put(BusProperties.NEXT_MODULE_CONCURRENCY, "6");
|
||||
producerProps.put(BinderProperties.MIN_PARTITION_COUNT, "5");
|
||||
producerProps.put(BinderProperties.NEXT_MODULE_CONCURRENCY, "6");
|
||||
Properties consumerProps = new Properties();
|
||||
consumerProps.put(BusProperties.MIN_PARTITION_COUNT, "5");
|
||||
consumerProps.put(BusProperties.CONCURRENCY, "6");
|
||||
consumerProps.put(BinderProperties.MIN_PARTITION_COUNT, "5");
|
||||
consumerProps.put(BinderProperties.CONCURRENCY, "6");
|
||||
long uniqueBindingId = System.currentTimeMillis();
|
||||
messageBus.bindProducer("foo" + uniqueBindingId + ".0", moduleOutputChannel, producerProps);
|
||||
messageBus.bindConsumer("foo" + uniqueBindingId + ".0", moduleInputChannel, consumerProps);
|
||||
binder.bindProducer("foo" + uniqueBindingId + ".0", moduleOutputChannel, producerProps);
|
||||
binder.bindConsumer("foo" + uniqueBindingId + ".0", moduleInputChannel, consumerProps);
|
||||
Message<?> message = org.springframework.integration.support.MessageBuilder.withPayload(ratherBigPayload).build();
|
||||
// Let the consumer actually bind to the producer before sending a msg
|
||||
busBindUnbindLatency();
|
||||
binderBindUnbindLatency();
|
||||
moduleOutputChannel.send(message);
|
||||
Message<?> inbound = moduleInputChannel.receive(2000);
|
||||
assertNotNull(inbound);
|
||||
assertArrayEquals(ratherBigPayload, (byte[]) inbound.getPayload());
|
||||
Collection<Partition> partitions = messageBus.getCoreMessageBus().getConnectionFactory().getPartitions(
|
||||
Collection<Partition> partitions = binder.getCoreBinder().getConnectionFactory().getPartitions(
|
||||
"foo" + uniqueBindingId + ".0");
|
||||
assertThat(partitions, hasSize(6));
|
||||
messageBus.unbindProducers("foo" + uniqueBindingId + ".0");
|
||||
messageBus.unbindConsumers("foo" + uniqueBindingId + ".0");
|
||||
binder.unbindProducers("foo" + uniqueBindingId + ".0");
|
||||
binder.unbindConsumers("foo" + uniqueBindingId + ".0");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -214,31 +220,31 @@ public class KafkaMessageBusTests extends PartitionCapableBusTests {
|
||||
|
||||
byte[] ratherBigPayload = new byte[2048];
|
||||
Arrays.fill(ratherBigPayload, (byte) 65);
|
||||
KafkaTestMessageBus messageBus = (KafkaTestMessageBus) getMessageBus();
|
||||
KafkaTestBinder binder = (KafkaTestBinder) getBinder();
|
||||
|
||||
DirectChannel moduleOutputChannel = new DirectChannel();
|
||||
QueueChannel moduleInputChannel = new QueueChannel();
|
||||
Properties producerProps = new Properties();
|
||||
producerProps.put(BusProperties.MIN_PARTITION_COUNT, "6");
|
||||
producerProps.put(BusProperties.NEXT_MODULE_CONCURRENCY, "5");
|
||||
producerProps.put(BinderProperties.MIN_PARTITION_COUNT, "6");
|
||||
producerProps.put(BinderProperties.NEXT_MODULE_CONCURRENCY, "5");
|
||||
Properties consumerProps = new Properties();
|
||||
consumerProps.put(BusProperties.MIN_PARTITION_COUNT, "6");
|
||||
consumerProps.put(BusProperties.CONCURRENCY, "5");
|
||||
consumerProps.put(BinderProperties.MIN_PARTITION_COUNT, "6");
|
||||
consumerProps.put(BinderProperties.CONCURRENCY, "5");
|
||||
long uniqueBindingId = System.currentTimeMillis();
|
||||
messageBus.bindProducer("foo" + uniqueBindingId + ".0", moduleOutputChannel, producerProps);
|
||||
messageBus.bindConsumer("foo" + uniqueBindingId + ".0", moduleInputChannel, consumerProps);
|
||||
binder.bindProducer("foo" + uniqueBindingId + ".0", moduleOutputChannel, producerProps);
|
||||
binder.bindConsumer("foo" + uniqueBindingId + ".0", moduleInputChannel, consumerProps);
|
||||
Message<?> message = org.springframework.integration.support.MessageBuilder.withPayload(ratherBigPayload).build();
|
||||
// Let the consumer actually bind to the producer before sending a msg
|
||||
busBindUnbindLatency();
|
||||
binderBindUnbindLatency();
|
||||
moduleOutputChannel.send(message);
|
||||
Message<?> inbound = moduleInputChannel.receive(2000);
|
||||
assertNotNull(inbound);
|
||||
assertArrayEquals(ratherBigPayload, (byte[]) inbound.getPayload());
|
||||
Collection<Partition> partitions = messageBus.getCoreMessageBus().getConnectionFactory().getPartitions(
|
||||
Collection<Partition> partitions = binder.getCoreBinder().getConnectionFactory().getPartitions(
|
||||
"foo" + uniqueBindingId + ".0");
|
||||
assertThat(partitions, hasSize(6));
|
||||
messageBus.unbindProducers("foo" + uniqueBindingId + ".0");
|
||||
messageBus.unbindConsumers("foo" + uniqueBindingId + ".0");
|
||||
binder.unbindProducers("foo" + uniqueBindingId + ".0");
|
||||
binder.unbindConsumers("foo" + uniqueBindingId + ".0");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -246,31 +252,31 @@ public class KafkaMessageBusTests extends PartitionCapableBusTests {
|
||||
|
||||
byte[] ratherBigPayload = new byte[2048];
|
||||
Arrays.fill(ratherBigPayload, (byte) 65);
|
||||
KafkaTestMessageBus messageBus = (KafkaTestMessageBus) getMessageBus();
|
||||
KafkaTestBinder binder = (KafkaTestBinder) getBinder();
|
||||
|
||||
DirectChannel moduleOutputChannel = new DirectChannel();
|
||||
QueueChannel moduleInputChannel = new QueueChannel();
|
||||
Properties producerProperties = new Properties();
|
||||
producerProperties.put(BusProperties.MIN_PARTITION_COUNT, "3");
|
||||
producerProperties.put(BusProperties.NEXT_MODULE_COUNT, "5");
|
||||
producerProperties.put(BusProperties.PARTITION_KEY_EXPRESSION, "payload");
|
||||
producerProperties.put(BinderProperties.MIN_PARTITION_COUNT, "3");
|
||||
producerProperties.put(BinderProperties.NEXT_MODULE_COUNT, "5");
|
||||
producerProperties.put(BinderProperties.PARTITION_KEY_EXPRESSION, "payload");
|
||||
Properties consumerProperties = new Properties();
|
||||
consumerProperties.put(BusProperties.MIN_PARTITION_COUNT, "3");
|
||||
consumerProperties.put(BinderProperties.MIN_PARTITION_COUNT, "3");
|
||||
long uniqueBindingId = System.currentTimeMillis();
|
||||
messageBus.bindProducer("foo" + uniqueBindingId + ".0", moduleOutputChannel, producerProperties);
|
||||
messageBus.bindConsumer("foo" + uniqueBindingId + ".0", moduleInputChannel, consumerProperties);
|
||||
binder.bindProducer("foo" + uniqueBindingId + ".0", moduleOutputChannel, producerProperties);
|
||||
binder.bindConsumer("foo" + uniqueBindingId + ".0", moduleInputChannel, consumerProperties);
|
||||
Message<?> message = org.springframework.integration.support.MessageBuilder.withPayload(ratherBigPayload).build();
|
||||
// Let the consumer actually bind to the producer before sending a msg
|
||||
busBindUnbindLatency();
|
||||
binderBindUnbindLatency();
|
||||
moduleOutputChannel.send(message);
|
||||
Message<?> inbound = moduleInputChannel.receive(2000);
|
||||
assertNotNull(inbound);
|
||||
assertArrayEquals(ratherBigPayload, (byte[]) inbound.getPayload());
|
||||
Collection<Partition> partitions = messageBus.getCoreMessageBus().getConnectionFactory().getPartitions(
|
||||
Collection<Partition> partitions = binder.getCoreBinder().getConnectionFactory().getPartitions(
|
||||
"foo" + uniqueBindingId + ".0");
|
||||
assertThat(partitions, hasSize(5));
|
||||
messageBus.unbindProducers("foo" + uniqueBindingId + ".0");
|
||||
messageBus.unbindConsumers("foo" + uniqueBindingId + ".0");
|
||||
binder.unbindProducers("foo" + uniqueBindingId + ".0");
|
||||
binder.unbindConsumers("foo" + uniqueBindingId + ".0");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -278,35 +284,35 @@ public class KafkaMessageBusTests extends PartitionCapableBusTests {
|
||||
|
||||
byte[] ratherBigPayload = new byte[2048];
|
||||
Arrays.fill(ratherBigPayload, (byte) 65);
|
||||
KafkaTestMessageBus messageBus = (KafkaTestMessageBus) getMessageBus();
|
||||
KafkaTestBinder binder = (KafkaTestBinder) getBinder();
|
||||
|
||||
DirectChannel moduleOutputChannel = new DirectChannel();
|
||||
QueueChannel moduleInputChannel = new QueueChannel();
|
||||
Properties producerProperties = new Properties();
|
||||
producerProperties.put(BusProperties.MIN_PARTITION_COUNT, "5");
|
||||
producerProperties.put(BusProperties.NEXT_MODULE_COUNT, "3");
|
||||
producerProperties.put(BusProperties.PARTITION_KEY_EXPRESSION, "payload");
|
||||
producerProperties.put(BinderProperties.MIN_PARTITION_COUNT, "5");
|
||||
producerProperties.put(BinderProperties.NEXT_MODULE_COUNT, "3");
|
||||
producerProperties.put(BinderProperties.PARTITION_KEY_EXPRESSION, "payload");
|
||||
Properties consumerProperties = new Properties();
|
||||
consumerProperties.put(BusProperties.MIN_PARTITION_COUNT, "5");
|
||||
consumerProperties.put(BinderProperties.MIN_PARTITION_COUNT, "5");
|
||||
long uniqueBindingId = System.currentTimeMillis();
|
||||
messageBus.bindProducer("foo" + uniqueBindingId + ".0", moduleOutputChannel, producerProperties);
|
||||
messageBus.bindConsumer("foo" + uniqueBindingId + ".0", moduleInputChannel, consumerProperties);
|
||||
binder.bindProducer("foo" + uniqueBindingId + ".0", moduleOutputChannel, producerProperties);
|
||||
binder.bindConsumer("foo" + uniqueBindingId + ".0", moduleInputChannel, consumerProperties);
|
||||
Message<?> message = org.springframework.integration.support.MessageBuilder.withPayload(ratherBigPayload).build();
|
||||
// Let the consumer actually bind to the producer before sending a msg
|
||||
busBindUnbindLatency();
|
||||
binderBindUnbindLatency();
|
||||
moduleOutputChannel.send(message);
|
||||
Message<?> inbound = moduleInputChannel.receive(2000);
|
||||
assertNotNull(inbound);
|
||||
assertArrayEquals(ratherBigPayload, (byte[]) inbound.getPayload());
|
||||
Collection<Partition> partitions = messageBus.getCoreMessageBus().getConnectionFactory().getPartitions(
|
||||
Collection<Partition> partitions = binder.getCoreBinder().getConnectionFactory().getPartitions(
|
||||
"foo" + uniqueBindingId + ".0");
|
||||
assertThat(partitions, hasSize(5));
|
||||
messageBus.unbindProducers("foo" + uniqueBindingId + ".0");
|
||||
messageBus.unbindConsumers("foo" + uniqueBindingId + ".0");
|
||||
binder.unbindProducers("foo" + uniqueBindingId + ".0");
|
||||
binder.unbindConsumers("foo" + uniqueBindingId + ".0");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Kafka message bus does not support direct binding")
|
||||
@Ignore("Kafka binder does not support direct binding")
|
||||
@Override
|
||||
public void testDirectBinding() throws Exception {
|
||||
|
||||
@@ -14,49 +14,47 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus.kafka;
|
||||
package org.springframework.cloud.stream.binder.kafka;
|
||||
|
||||
import org.springframework.cloud.stream.binder.AbstractTestBinder;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.integration.kafka.support.ZookeeperConnect;
|
||||
import org.springframework.xd.dirt.integration.bus.AbstractTestMessageBus;
|
||||
import org.springframework.xd.dirt.integration.bus.serializer.MultiTypeCodec;
|
||||
import org.springframework.xd.dirt.integration.bus.serializer.kryo.PojoCodec;
|
||||
import org.springframework.xd.dirt.integration.kafka.KafkaMessageBus;
|
||||
import org.springframework.xd.dirt.integration.kafka.TestKafkaCluster;
|
||||
import org.springframework.xd.dirt.integration.kafka.KafkaTestSupport;
|
||||
import org.springframework.xd.dirt.integration.kafka.KafkaMessageChannelBinder;
|
||||
import org.springframework.xd.tuple.serializer.kryo.TupleKryoRegistrar;
|
||||
|
||||
|
||||
/**
|
||||
* Test support class for {@link KafkaMessageBus}.
|
||||
* Creates a bus that uses a test {@link TestKafkaCluster kafka cluster}.
|
||||
* Test support class for {@link org.springframework.xd.dirt.integration.kafka.KafkaMessageChannelBinder}.
|
||||
* Creates a binder that uses a test {@link TestKafkaCluster kafka cluster}.
|
||||
* @author Eric Bottard
|
||||
* @author Marius Bogoevici
|
||||
* @author David Turanski
|
||||
*/
|
||||
public class KafkaTestMessageBus extends AbstractTestMessageBus<KafkaMessageBus> {
|
||||
public class KafkaTestBinder extends AbstractTestBinder<KafkaMessageChannelBinder> {
|
||||
|
||||
public KafkaTestMessageBus(KafkaTestSupport kafkaTestSupport) {
|
||||
this(kafkaTestSupport, getCodec(), KafkaMessageBus.Mode.embeddedHeaders);
|
||||
public KafkaTestBinder(KafkaTestSupport kafkaTestSupport) {
|
||||
this(kafkaTestSupport, getCodec(), KafkaMessageChannelBinder.Mode.embeddedHeaders);
|
||||
}
|
||||
|
||||
|
||||
public KafkaTestMessageBus(KafkaTestSupport kafkaTestSupport, MultiTypeCodec<Object> codec,
|
||||
KafkaMessageBus.Mode mode) {
|
||||
public KafkaTestBinder(KafkaTestSupport kafkaTestSupport, MultiTypeCodec<Object> codec,
|
||||
KafkaMessageChannelBinder.Mode mode) {
|
||||
|
||||
try {
|
||||
ZookeeperConnect zookeeperConnect = new ZookeeperConnect();
|
||||
zookeeperConnect.setZkConnect(kafkaTestSupport.getZkConnectString());
|
||||
KafkaMessageBus messageBus = new KafkaMessageBus(zookeeperConnect,
|
||||
KafkaMessageChannelBinder binder = new KafkaMessageChannelBinder(zookeeperConnect,
|
||||
kafkaTestSupport.getBrokerAddress(),
|
||||
kafkaTestSupport.getZkConnectString(), codec);
|
||||
messageBus.setDefaultBatchingEnabled(false);
|
||||
messageBus.setMode(mode);
|
||||
messageBus.afterPropertiesSet();
|
||||
binder.setDefaultBatchingEnabled(false);
|
||||
binder.setMode(mode);
|
||||
binder.afterPropertiesSet();
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.refresh();
|
||||
messageBus.setApplicationContext(context);
|
||||
this.setMessageBus(messageBus);
|
||||
binder.setApplicationContext(context);
|
||||
this.setBinder(binder);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.kafka;
|
||||
package org.springframework.cloud.stream.binder.kafka;
|
||||
|
||||
|
||||
import java.util.Properties;
|
||||
@@ -34,7 +34,7 @@ import org.junit.Rule;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.xd.test.AbstractExternalResourceTestSupport;
|
||||
import org.springframework.cloud.stream.binder.AbstractExternalResourceTestSupport;
|
||||
|
||||
/**
|
||||
* JUnit {@link Rule} that starts an embedded Kafka server (with an associated Zookeeper)
|
||||
@@ -14,11 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus.kafka;
|
||||
package org.springframework.cloud.stream.binder.kafka;
|
||||
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.xd.dirt.integration.bus.PartitionKeyExtractorStrategy;
|
||||
import org.springframework.xd.dirt.integration.bus.PartitionSelectorStrategy;
|
||||
import org.springframework.cloud.stream.binder.PartitionKeyExtractorStrategy;
|
||||
import org.springframework.cloud.stream.binder.PartitionSelectorStrategy;
|
||||
|
||||
|
||||
/**
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus.kafka;
|
||||
package org.springframework.cloud.stream.binder.kafka;
|
||||
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
@@ -32,6 +32,7 @@ import java.util.Properties;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.cloud.stream.binder.BinderHeaders;
|
||||
import org.springframework.integration.IntegrationMessageHeaderAccessor;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
@@ -41,39 +42,38 @@ import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.xd.dirt.integration.bus.Binding;
|
||||
import org.springframework.xd.dirt.integration.bus.BusProperties;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageBus;
|
||||
import org.springframework.xd.dirt.integration.bus.XdHeaders;
|
||||
import org.springframework.xd.dirt.integration.kafka.KafkaMessageBus;
|
||||
import org.springframework.xd.test.TestUtils;
|
||||
import org.springframework.cloud.stream.binder.Binding;
|
||||
import org.springframework.cloud.stream.binder.BinderProperties;
|
||||
import org.springframework.cloud.stream.binder.Binder;
|
||||
import org.springframework.xd.dirt.integration.kafka.KafkaMessageChannelBinder;
|
||||
import org.springframework.cloud.stream.binder.TestUtils;
|
||||
|
||||
/**
|
||||
* @author Marius Bogoevici
|
||||
*/
|
||||
|
||||
public class RawModeKafkaMessageBusTests extends KafkaMessageBusTests {
|
||||
public class RawModeKafkaBinderTests extends KafkaBinderTests {
|
||||
|
||||
@Override
|
||||
protected KafkaTestMessageBus createKafkaTestMessageBus() {
|
||||
return new KafkaTestMessageBus(kafkaTestSupport, getCodec(), KafkaMessageBus.Mode.raw);
|
||||
protected KafkaTestBinder createKafkaTestBinder() {
|
||||
return new KafkaTestBinder(kafkaTestSupport, getCodec(), KafkaMessageChannelBinder.Mode.raw);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testPartitionedModuleJava() throws Exception {
|
||||
MessageBus bus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
Properties properties = new Properties();
|
||||
properties.put("partitionKeyExtractorClass", "org.springframework.xd.dirt.integration.bus.kafka.RawKafkaPartitionTestSupport");
|
||||
properties.put("partitionSelectorClass", "org.springframework.xd.dirt.integration.bus.kafka.RawKafkaPartitionTestSupport");
|
||||
properties.put(BusProperties.NEXT_MODULE_COUNT, "3");
|
||||
properties.put(BusProperties.NEXT_MODULE_CONCURRENCY, "2");
|
||||
properties.put("partitionKeyExtractorClass", "org.springframework.cloud.stream.binder.kafka.RawKafkaPartitionTestSupport");
|
||||
properties.put("partitionSelectorClass", "org.springframework.cloud.stream.binder.kafka.RawKafkaPartitionTestSupport");
|
||||
properties.put(BinderProperties.NEXT_MODULE_COUNT, "3");
|
||||
properties.put(BinderProperties.NEXT_MODULE_CONCURRENCY, "2");
|
||||
|
||||
DirectChannel output = new DirectChannel();
|
||||
output.setBeanName("test.output");
|
||||
bus.bindProducer("partJ.0", output, properties);
|
||||
binder.bindProducer("partJ.0", output, properties);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(bus, "messageBus.bindings", List.class);
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(binder, "binder.bindings", List.class);
|
||||
assertEquals(1, bindings.size());
|
||||
|
||||
properties.clear();
|
||||
@@ -82,15 +82,15 @@ public class RawModeKafkaMessageBusTests extends KafkaMessageBusTests {
|
||||
properties.put("partitionIndex", "0");
|
||||
QueueChannel input0 = new QueueChannel();
|
||||
input0.setBeanName("test.input0J");
|
||||
bus.bindConsumer("partJ.0", input0, properties);
|
||||
binder.bindConsumer("partJ.0", input0, properties);
|
||||
properties.put("partitionIndex", "1");
|
||||
QueueChannel input1 = new QueueChannel();
|
||||
input1.setBeanName("test.input1J");
|
||||
bus.bindConsumer("partJ.0", input1, properties);
|
||||
binder.bindConsumer("partJ.0", input1, properties);
|
||||
properties.put("partitionIndex", "2");
|
||||
QueueChannel input2 = new QueueChannel();
|
||||
input2.setBeanName("test.input2J");
|
||||
bus.bindConsumer("partJ.0", input2, properties);
|
||||
binder.bindConsumer("partJ.0", input2, properties);
|
||||
|
||||
output.send(new GenericMessage<>(new byte[]{(byte)0}));
|
||||
output.send(new GenericMessage<>(new byte[]{(byte)1}));
|
||||
@@ -109,25 +109,25 @@ public class RawModeKafkaMessageBusTests extends KafkaMessageBusTests {
|
||||
((byte[]) receive2.getPayload())[0]),
|
||||
containsInAnyOrder((byte)0, (byte)1, (byte)2));
|
||||
|
||||
bus.unbindConsumers("partJ.0");
|
||||
bus.unbindProducers("partJ.0");
|
||||
binder.unbindConsumers("partJ.0");
|
||||
binder.unbindProducers("partJ.0");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testPartitionedModuleSpEL() throws Exception {
|
||||
MessageBus bus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
Properties properties = new Properties();
|
||||
properties.put("partitionKeyExpression", "payload[0]");
|
||||
properties.put("partitionSelectorExpression", "hashCode()");
|
||||
properties.put(BusProperties.NEXT_MODULE_COUNT, "3");
|
||||
properties.put(BusProperties.NEXT_MODULE_CONCURRENCY, "2");
|
||||
properties.put(BinderProperties.NEXT_MODULE_COUNT, "3");
|
||||
properties.put(BinderProperties.NEXT_MODULE_CONCURRENCY, "2");
|
||||
|
||||
DirectChannel output = new DirectChannel();
|
||||
output.setBeanName("test.output");
|
||||
bus.bindProducer("part.0", output, properties);
|
||||
binder.bindProducer("part.0", output, properties);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(bus, "messageBus.bindings", List.class);
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(binder, "binder.bindings", List.class);
|
||||
assertEquals(1, bindings.size());
|
||||
try {
|
||||
AbstractEndpoint endpoint = bindings.get(0).getEndpoint();
|
||||
@@ -143,15 +143,15 @@ public class RawModeKafkaMessageBusTests extends KafkaMessageBusTests {
|
||||
properties.put("count","3");
|
||||
QueueChannel input0 = new QueueChannel();
|
||||
input0.setBeanName("test.input0S");
|
||||
bus.bindConsumer("part.0", input0, properties);
|
||||
binder.bindConsumer("part.0", input0, properties);
|
||||
properties.put("partitionIndex", "1");
|
||||
QueueChannel input1 = new QueueChannel();
|
||||
input1.setBeanName("test.input1S");
|
||||
bus.bindConsumer("part.0", input1, properties);
|
||||
binder.bindConsumer("part.0", input1, properties);
|
||||
properties.put("partitionIndex", "2");
|
||||
QueueChannel input2 = new QueueChannel();
|
||||
input2.setBeanName("test.input2S");
|
||||
bus.bindConsumer("part.0", input2, properties);
|
||||
binder.bindConsumer("part.0", input2, properties);
|
||||
|
||||
Message<byte[]> message2 = MessageBuilder.withPayload(new byte[]{2})
|
||||
.setHeader(IntegrationMessageHeaderAccessor.CORRELATION_ID, "foo")
|
||||
@@ -177,14 +177,14 @@ public class RawModeKafkaMessageBusTests extends KafkaMessageBusTests {
|
||||
((byte[]) receive2.getPayload())[0]),
|
||||
containsInAnyOrder((byte)0, (byte)1, (byte)2));
|
||||
|
||||
bus.unbindConsumers("part.0");
|
||||
bus.unbindProducers("part.0");
|
||||
binder.unbindConsumers("part.0");
|
||||
binder.unbindProducers("part.0");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void createInboundPubSubBeforeOutboundPubSub() throws Exception {
|
||||
MessageBus messageBus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
DirectChannel moduleOutputChannel = new DirectChannel();
|
||||
// Test pub/sub by emulating how StreamPlugin handles taps
|
||||
DirectChannel tapChannel = new DirectChannel();
|
||||
@@ -192,18 +192,18 @@ public class RawModeKafkaMessageBusTests extends KafkaMessageBusTests {
|
||||
QueueChannel module2InputChannel = new QueueChannel();
|
||||
QueueChannel module3InputChannel = new QueueChannel();
|
||||
// Create the tap first
|
||||
String fooTapName = messageBus.isCapable(MessageBus.Capability.DURABLE_PUBSUB) ? "foo.tap:baz.http" : "tap:baz.http";
|
||||
messageBus.bindPubSubConsumer(fooTapName, module2InputChannel, null);
|
||||
String fooTapName = binder.isCapable(Binder.Capability.DURABLE_PUBSUB) ? "foo.tap:baz.http" : "tap:baz.http";
|
||||
binder.bindPubSubConsumer(fooTapName, module2InputChannel, null);
|
||||
|
||||
// Then create the stream
|
||||
messageBus.bindProducer("baz.0", moduleOutputChannel, null);
|
||||
messageBus.bindConsumer("baz.0", moduleInputChannel, null);
|
||||
binder.bindProducer("baz.0", moduleOutputChannel, null);
|
||||
binder.bindConsumer("baz.0", moduleInputChannel, null);
|
||||
moduleOutputChannel.addInterceptor(new WireTap(tapChannel));
|
||||
messageBus.bindPubSubProducer("tap:baz.http", tapChannel, null);
|
||||
binder.bindPubSubProducer("tap:baz.http", tapChannel, null);
|
||||
|
||||
// Another new module is using tap as an input channel
|
||||
String barTapName = messageBus.isCapable(MessageBus.Capability.DURABLE_PUBSUB) ? "bar.tap:baz.http" : "tap:baz.http";
|
||||
messageBus.bindPubSubConsumer(barTapName, module3InputChannel, null);
|
||||
String barTapName = binder.isCapable(Binder.Capability.DURABLE_PUBSUB) ? "bar.tap:baz.http" : "tap:baz.http";
|
||||
binder.bindPubSubConsumer(barTapName, module3InputChannel, null);
|
||||
Message<?> message = MessageBuilder.withPayload("foo".getBytes()).setHeader(MessageHeaders.CONTENT_TYPE, "foo/bar").build();
|
||||
boolean success = false;
|
||||
boolean retried = false;
|
||||
@@ -222,11 +222,11 @@ public class RawModeKafkaMessageBusTests extends KafkaMessageBusTests {
|
||||
}
|
||||
success = true;
|
||||
assertEquals("foo", new String((byte[]) tapped1.getPayload()));
|
||||
assertNull(tapped1.getHeaders().get(XdHeaders.XD_ORIGINAL_CONTENT_TYPE));
|
||||
assertNull(tapped1.getHeaders().get(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE));
|
||||
assertEquals("foo", new String((byte[])tapped2.getPayload()));
|
||||
}
|
||||
// delete one tap stream is deleted
|
||||
messageBus.unbindConsumer(barTapName, module3InputChannel);
|
||||
binder.unbindConsumer(barTapName, module3InputChannel);
|
||||
Message<?> message2 = MessageBuilder.withPayload("bar".getBytes()).setHeader(MessageHeaders.CONTENT_TYPE, "foo/bar").build();
|
||||
moduleOutputChannel.send(message2);
|
||||
|
||||
@@ -238,31 +238,31 @@ public class RawModeKafkaMessageBusTests extends KafkaMessageBusTests {
|
||||
assertNull(module3InputChannel.receive(1000));
|
||||
|
||||
// when other tap stream is deleted
|
||||
messageBus.unbindConsumer(fooTapName, module2InputChannel);
|
||||
binder.unbindConsumer(fooTapName, module2InputChannel);
|
||||
// Clean up as StreamPlugin would
|
||||
messageBus.unbindConsumer("baz.0", moduleInputChannel);
|
||||
messageBus.unbindProducer("baz.0", moduleOutputChannel);
|
||||
messageBus.unbindProducers("tap:baz.http");
|
||||
assertTrue(getBindings(messageBus).isEmpty());
|
||||
binder.unbindConsumer("baz.0", moduleInputChannel);
|
||||
binder.unbindProducer("baz.0", moduleOutputChannel);
|
||||
binder.unbindProducers("tap:baz.http");
|
||||
assertTrue(getBindings(binder).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testSendAndReceive() throws Exception {
|
||||
MessageBus messageBus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
DirectChannel moduleOutputChannel = new DirectChannel();
|
||||
QueueChannel moduleInputChannel = new QueueChannel();
|
||||
messageBus.bindProducer("foo.0", moduleOutputChannel, null);
|
||||
messageBus.bindConsumer("foo.0", moduleInputChannel, null);
|
||||
binder.bindProducer("foo.0", moduleOutputChannel, null);
|
||||
binder.bindConsumer("foo.0", moduleInputChannel, null);
|
||||
Message<?> message = MessageBuilder.withPayload("foo".getBytes()).build();
|
||||
// Let the consumer actually bind to the producer before sending a msg
|
||||
busBindUnbindLatency();
|
||||
binderBindUnbindLatency();
|
||||
moduleOutputChannel.send(message);
|
||||
Message<?> inbound = moduleInputChannel.receive(5000);
|
||||
assertNotNull(inbound);
|
||||
assertEquals("foo", new String((byte[])inbound.getPayload()));
|
||||
messageBus.unbindProducers("foo.0");
|
||||
messageBus.unbindConsumers("foo.0");
|
||||
binder.unbindProducers("foo.0");
|
||||
binder.unbindConsumers("foo.0");
|
||||
}
|
||||
|
||||
// Ignored, since raw mode does not support headers
|
||||
@@ -275,23 +275,23 @@ public class RawModeKafkaMessageBusTests extends KafkaMessageBusTests {
|
||||
|
||||
@Test
|
||||
public void testSendAndReceivePubSub() throws Exception {
|
||||
MessageBus messageBus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
DirectChannel moduleOutputChannel = new DirectChannel();
|
||||
// Test pub/sub by emulating how StreamPlugin handles taps
|
||||
DirectChannel tapChannel = new DirectChannel();
|
||||
QueueChannel moduleInputChannel = new QueueChannel();
|
||||
QueueChannel module2InputChannel = new QueueChannel();
|
||||
QueueChannel module3InputChannel = new QueueChannel();
|
||||
messageBus.bindProducer("baz.0", moduleOutputChannel, null);
|
||||
messageBus.bindConsumer("baz.0", moduleInputChannel, null);
|
||||
binder.bindProducer("baz.0", moduleOutputChannel, null);
|
||||
binder.bindConsumer("baz.0", moduleInputChannel, null);
|
||||
moduleOutputChannel.addInterceptor(new WireTap(tapChannel));
|
||||
messageBus.bindPubSubProducer("tap:baz.http", tapChannel, null);
|
||||
binder.bindPubSubProducer("tap:baz.http", tapChannel, null);
|
||||
// A new module is using the tap as an input channel
|
||||
String fooTapName = messageBus.isCapable(MessageBus.Capability.DURABLE_PUBSUB) ? "foo.tap:baz.http" : "tap:baz.http";
|
||||
messageBus.bindPubSubConsumer(fooTapName, module2InputChannel, null);
|
||||
String fooTapName = binder.isCapable(Binder.Capability.DURABLE_PUBSUB) ? "foo.tap:baz.http" : "tap:baz.http";
|
||||
binder.bindPubSubConsumer(fooTapName, module2InputChannel, null);
|
||||
// Another new module is using tap as an input channel
|
||||
String barTapName = messageBus.isCapable(MessageBus.Capability.DURABLE_PUBSUB) ? "bar.tap:baz.http" : "tap:baz.http";
|
||||
messageBus.bindPubSubConsumer(barTapName, module3InputChannel, null);
|
||||
String barTapName = binder.isCapable(Binder.Capability.DURABLE_PUBSUB) ? "bar.tap:baz.http" : "tap:baz.http";
|
||||
binder.bindPubSubConsumer(barTapName, module3InputChannel, null);
|
||||
Message<?> message = MessageBuilder.withPayload("foo".getBytes()).build();
|
||||
boolean success = false;
|
||||
boolean retried = false;
|
||||
@@ -314,7 +314,7 @@ public class RawModeKafkaMessageBusTests extends KafkaMessageBusTests {
|
||||
assertEquals("foo", new String((byte[])tapped2.getPayload()));
|
||||
}
|
||||
// delete one tap stream is deleted
|
||||
messageBus.unbindConsumer(barTapName, module3InputChannel);
|
||||
binder.unbindConsumer(barTapName, module3InputChannel);
|
||||
Message<?> message2 = MessageBuilder.withPayload("bar".getBytes()).build();
|
||||
moduleOutputChannel.send(message2);
|
||||
|
||||
@@ -326,12 +326,12 @@ public class RawModeKafkaMessageBusTests extends KafkaMessageBusTests {
|
||||
assertNull(module3InputChannel.receive(1000));
|
||||
|
||||
// when other tap stream is deleted
|
||||
messageBus.unbindConsumer(fooTapName, module2InputChannel);
|
||||
binder.unbindConsumer(fooTapName, module2InputChannel);
|
||||
// Clean up as StreamPlugin would
|
||||
messageBus.unbindConsumer("baz.0", moduleInputChannel);
|
||||
messageBus.unbindProducer("baz.0", moduleOutputChannel);
|
||||
messageBus.unbindProducers("tap:baz.http");
|
||||
assertTrue(getBindings(messageBus).isEmpty());
|
||||
binder.unbindConsumer("baz.0", moduleInputChannel);
|
||||
binder.unbindProducer("baz.0", moduleOutputChannel);
|
||||
binder.unbindProducers("tap:baz.http");
|
||||
assertTrue(getBindings(binder).isEmpty());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.kafka;
|
||||
package org.springframework.cloud.stream.binder.kafka;
|
||||
|
||||
import kafka.admin.AdminUtils;
|
||||
import kafka.consumer.Consumer;
|
||||
@@ -35,6 +35,7 @@ import org.apache.curator.test.TestingServer;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.SocketUtils;
|
||||
import org.springframework.xd.dirt.integration.kafka.KafkaMessageChannelBinder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
@@ -90,7 +91,7 @@ public class TestKafkaCluster {
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
TestKafkaCluster cluster = new TestKafkaCluster();
|
||||
ZkClient client = new ZkClient(cluster.getZkConnectString(), 10000, 10000, KafkaMessageBus.utf8Serializer);
|
||||
ZkClient client = new ZkClient(cluster.getZkConnectString(), 10000, 10000, KafkaMessageChannelBinder.utf8Serializer);
|
||||
int partitions = 5;
|
||||
int replication = 1;
|
||||
AdminUtils.createTopic(client, "mytopic", partitions, replication, new Properties());
|
||||
@@ -3,14 +3,14 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-cloud-stream-binding-local</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-local</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>spring-cloud-stream-binding-local</name>
|
||||
<description>Local(in memory) binding implementation</description>
|
||||
<name>spring-cloud-stream-binder-local</name>
|
||||
<description>Local(in memory) binder implementation</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-bindings-parent</artifactId>
|
||||
<artifactId>spring-cloud-stream-binders-parent</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-spi</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-test</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-test</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -11,7 +11,7 @@
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus.local;
|
||||
package org.springframework.cloud.stream.binder.local;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@@ -37,13 +37,13 @@ import org.springframework.messaging.SubscribableChannel;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.xd.dirt.integration.bus.AbstractBusPropertiesAccessor;
|
||||
import org.springframework.xd.dirt.integration.bus.Binding;
|
||||
import org.springframework.xd.dirt.integration.bus.BusProperties;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageBusSupport;
|
||||
import org.springframework.cloud.stream.binder.AbstractBinderPropertiesAccessor;
|
||||
import org.springframework.cloud.stream.binder.Binding;
|
||||
import org.springframework.cloud.stream.binder.BinderProperties;
|
||||
import org.springframework.cloud.stream.binder.MessageChannelBinderSupport;
|
||||
|
||||
/**
|
||||
* A simple implementation of {@link org.springframework.xd.dirt.integration.bus.MessageBus} for in-process use. For inbound and outbound, creates a
|
||||
* A simple implementation of {@link org.springframework.cloud.stream.binder.Binder} for in-process use. For inbound and outbound, creates a
|
||||
* {@link DirectChannel} or a {@link QueueChannel} depending on whether the binding is aliased or not then bridges the
|
||||
* passed {@link MessageChannel} to the channel which is registered in the given application context. If that channel
|
||||
* does not yet exist, it will be created.
|
||||
@@ -55,7 +55,7 @@ import org.springframework.xd.dirt.integration.bus.MessageBusSupport;
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @since 1.0
|
||||
*/
|
||||
public class LocalMessageBus extends MessageBusSupport {
|
||||
public class LocalMessageChannelBinder extends MessageChannelBinderSupport {
|
||||
|
||||
private static final int DEFAULT_EXECUTOR_CORE_POOL_SIZE = 0;
|
||||
|
||||
@@ -69,9 +69,11 @@ public class LocalMessageBus extends MessageBusSupport {
|
||||
|
||||
protected static final Set<Object> CONSUMER_REQUEST_REPLY_PROPERTIES = new SetBuilder()
|
||||
.addAll(CONSUMER_STANDARD_PROPERTIES)
|
||||
.add(BusProperties.CONCURRENCY)
|
||||
.add(BinderProperties.CONCURRENCY)
|
||||
.build();
|
||||
|
||||
public static final String THREAD_NAME_PREFIX = "binder.local-";
|
||||
|
||||
private volatile PollerMetadata poller;
|
||||
|
||||
private final Map<String, ExecutorChannel> requestReplyChannels = new HashMap<String, ExecutorChannel>();
|
||||
@@ -173,12 +175,12 @@ public class LocalMessageBus extends MessageBusSupport {
|
||||
this.executor.setMaxPoolSize(this.executorMaxPoolSize);
|
||||
this.executor.setQueueCapacity(this.executorQueueSize);
|
||||
this.executor.setKeepAliveSeconds(this.executorKeepAliveSeconds);
|
||||
this.executor.setThreadNamePrefix("xd.localbus-");
|
||||
this.executor.setThreadNamePrefix(THREAD_NAME_PREFIX);
|
||||
this.executor.initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* For the local bus we bridge the router "output" channel to a queue channel; the queue
|
||||
* For the local binder we bridge the router "output" channel to a queue channel; the queue
|
||||
* channel gets the name and the source channel is named 'dynamic.output.to.' + name.
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@@ -188,7 +190,7 @@ public class LocalMessageBus extends MessageBusSupport {
|
||||
}
|
||||
|
||||
/**
|
||||
* For the local bus we bridge the router "output" channel to a pub/sub channel; the pub/sub
|
||||
* For the local binder we bridge the router "output" channel to a pub/sub channel; the pub/sub
|
||||
* channel gets the name and the source channel is named 'dynamic.output.to.' + name.
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@@ -230,7 +232,7 @@ public class LocalMessageBus extends MessageBusSupport {
|
||||
MessageChannel registeredChannel = channelProvider.lookupOrCreateSharedChannel(name);
|
||||
bridge(name, registeredChannel, moduleInputChannel,
|
||||
"inbound." + ((NamedComponent) registeredChannel).getComponentName(),
|
||||
new LocalBusPropertiesAccessor(properties));
|
||||
new LocalBinderPropertiesAccessor(properties));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -257,7 +259,7 @@ public class LocalMessageBus extends MessageBusSupport {
|
||||
MessageChannel registeredChannel = channelProvider.lookupOrCreateSharedChannel(name);
|
||||
bridge(name, moduleOutputChannel, registeredChannel,
|
||||
"outbound." + ((NamedComponent) registeredChannel).getComponentName(),
|
||||
new LocalBusPropertiesAccessor(properties));
|
||||
new LocalBinderPropertiesAccessor(properties));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -326,8 +328,8 @@ public class LocalMessageBus extends MessageBusSupport {
|
||||
|
||||
private ThreadPoolTaskExecutor createRequestReplyExecutor(String name, Properties properties) {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setCorePoolSize(new LocalBusPropertiesAccessor(properties).getConcurrency(DEFAULT_REQ_REPLY_CONCURRENCY));
|
||||
executor.setThreadNamePrefix("xd.localBus." + name + "-");
|
||||
executor.setCorePoolSize(new LocalBinderPropertiesAccessor(properties).getConcurrency(DEFAULT_REQ_REPLY_CONCURRENCY));
|
||||
executor.setThreadNamePrefix(THREAD_NAME_PREFIX + name + "-");
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
@@ -346,13 +348,13 @@ public class LocalMessageBus extends MessageBusSupport {
|
||||
}
|
||||
|
||||
protected BridgeHandler bridge(String name, MessageChannel from, MessageChannel to, String bridgeName,
|
||||
LocalBusPropertiesAccessor properties) {
|
||||
LocalBinderPropertiesAccessor properties) {
|
||||
return bridge(name, from, to, bridgeName, null, properties);
|
||||
}
|
||||
|
||||
|
||||
protected BridgeHandler bridge(String name, MessageChannel from, MessageChannel to, String bridgeName,
|
||||
final Collection<MimeType> acceptedMimeTypes, LocalBusPropertiesAccessor properties) {
|
||||
final Collection<MimeType> acceptedMimeTypes, LocalBinderPropertiesAccessor properties) {
|
||||
|
||||
final boolean isInbound = bridgeName.startsWith("inbound.");
|
||||
|
||||
@@ -407,9 +409,9 @@ public class LocalMessageBus extends MessageBusSupport {
|
||||
return getApplicationContext().getBean(name, requiredType);
|
||||
}
|
||||
|
||||
private static class LocalBusPropertiesAccessor extends AbstractBusPropertiesAccessor {
|
||||
private static class LocalBinderPropertiesAccessor extends AbstractBinderPropertiesAccessor {
|
||||
|
||||
public LocalBusPropertiesAccessor(Properties properties) {
|
||||
public LocalBinderPropertiesAccessor(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean id="messageBus" class="org.springframework.xd.dirt.integration.bus.local.LocalMessageBus">
|
||||
<bean id="messageBus" class="org.springframework.cloud.stream.binder.local.LocalMessageChannelBinder">
|
||||
<property name="queueSize"
|
||||
value="${xd.messagebus.local.queueSize: #{T(Integer).MAX_VALUE}}" />
|
||||
<property name="poller">
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus.local;
|
||||
package org.springframework.cloud.stream.binder.local;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@@ -25,6 +25,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.cloud.stream.binder.AbstractBinderTests;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
@@ -39,8 +40,7 @@ import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.xd.dirt.integration.bus.AbstractMessageBusTests;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageBus;
|
||||
import org.springframework.cloud.stream.binder.Binder;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@@ -53,33 +53,33 @@ import static org.junit.Assert.assertTrue;
|
||||
* @author David Turanski
|
||||
* @since 1.0
|
||||
*/
|
||||
public class LocalMessageBusTests extends AbstractMessageBusTests {
|
||||
public class LocalBinderTests extends AbstractBinderTests {
|
||||
|
||||
@Override
|
||||
protected MessageBus getMessageBus() throws Exception {
|
||||
LocalMessageBus bus = new LocalMessageBus();
|
||||
protected Binder getBinder() throws Exception {
|
||||
LocalMessageChannelBinder binder = new LocalMessageChannelBinder();
|
||||
GenericApplicationContext applicationContext = new GenericApplicationContext();
|
||||
applicationContext.getBeanFactory().registerSingleton(
|
||||
IntegrationUtils.INTEGRATION_MESSAGE_BUILDER_FACTORY_BEAN_NAME,
|
||||
new DefaultMessageBuilderFactory());
|
||||
applicationContext.refresh();
|
||||
bus.setApplicationContext(applicationContext);
|
||||
bus.setExecutorCorePoolSize(2);
|
||||
bus.setExecutorMaxPoolSize(10);
|
||||
bus.setExecutorKeepAliveSeconds(59);
|
||||
bus.setExecutorQueueSize(Integer.MAX_VALUE - 1);
|
||||
bus.afterPropertiesSet();
|
||||
return bus;
|
||||
binder.setApplicationContext(applicationContext);
|
||||
binder.setExecutorCorePoolSize(2);
|
||||
binder.setExecutorMaxPoolSize(10);
|
||||
binder.setExecutorKeepAliveSeconds(59);
|
||||
binder.setExecutorQueueSize(Integer.MAX_VALUE - 1);
|
||||
binder.afterPropertiesSet();
|
||||
return binder;
|
||||
}
|
||||
|
||||
protected Collection<?> getBindings(MessageBus testMessageBus) {
|
||||
return getBindingsFromMsgBus(testMessageBus);
|
||||
protected Collection<?> getBindings(Binder testBinder) {
|
||||
return getBindingsFromBinder(testBinder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProps() throws Exception {
|
||||
LocalMessageBus bus = (LocalMessageBus) getMessageBus();
|
||||
ThreadPoolTaskExecutor exec = TestUtils.getPropertyValue(bus, "executor", ThreadPoolTaskExecutor.class);
|
||||
LocalMessageChannelBinder binder = (LocalMessageChannelBinder) getBinder();
|
||||
ThreadPoolTaskExecutor exec = TestUtils.getPropertyValue(binder, "executor", ThreadPoolTaskExecutor.class);
|
||||
assertEquals(2, exec.getCorePoolSize());
|
||||
assertEquals(10, exec.getMaxPoolSize());
|
||||
assertEquals(59, exec.getKeepAliveSeconds());
|
||||
@@ -88,29 +88,29 @@ public class LocalMessageBusTests extends AbstractMessageBusTests {
|
||||
|
||||
@Test
|
||||
public void testPayloadConversionNotNeededExplicitType() throws Exception {
|
||||
LocalMessageBus bus = (LocalMessageBus) getMessageBus();
|
||||
verifyPayloadConversion(new TestPayload(), bus);
|
||||
LocalMessageChannelBinder binder = (LocalMessageChannelBinder) getBinder();
|
||||
verifyPayloadConversion(new TestPayload(), binder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoPayloadConversionByDefault() throws Exception {
|
||||
LocalMessageBus bus = (LocalMessageBus) getMessageBus();
|
||||
verifyPayloadConversion(new TestPayload(), bus);
|
||||
LocalMessageChannelBinder binder = (LocalMessageChannelBinder) getBinder();
|
||||
verifyPayloadConversion(new TestPayload(), binder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTapDoesntHurtStream() throws Exception {
|
||||
LocalMessageBus bus = (LocalMessageBus) getMessageBus();
|
||||
LocalMessageChannelBinder binder = (LocalMessageChannelBinder) getBinder();
|
||||
DirectChannel moduleOutputChannel = new DirectChannel();
|
||||
moduleOutputChannel.setBeanName("bangOut");
|
||||
DirectChannel tapChannel = new DirectChannel();
|
||||
tapChannel.setBeanName("tapChannel");
|
||||
WireTap tap = new WireTap(tapChannel);
|
||||
moduleOutputChannel.addInterceptor(tap);
|
||||
bus.bindProducer("bang.0", moduleOutputChannel, null);
|
||||
binder.bindProducer("bang.0", moduleOutputChannel, null);
|
||||
final AtomicBoolean messageReceived = new AtomicBoolean();
|
||||
final AtomicReference<Thread> streamThread = new AtomicReference<Thread>();
|
||||
bus.bindConsumer("bang.0", new DirectChannel() {
|
||||
binder.bindConsumer("bang.0", new DirectChannel() {
|
||||
|
||||
@Override
|
||||
protected boolean doSend(Message<?> message, long timeout) {
|
||||
@@ -121,8 +121,8 @@ public class LocalMessageBusTests extends AbstractMessageBusTests {
|
||||
}, null);
|
||||
final CountDownLatch tapped = new CountDownLatch(1);
|
||||
final AtomicReference<Thread> tapThread = new AtomicReference<Thread>();
|
||||
bus.bindPubSubProducer("tap:stream:bang.0", tapChannel, null);
|
||||
bus.bindPubSubConsumer("tap:stream:bang.0", new DirectChannel() {
|
||||
binder.bindPubSubProducer("tap:stream:bang.0", tapChannel, null);
|
||||
binder.bindPubSubConsumer("tap:stream:bang.0", new DirectChannel() {
|
||||
|
||||
@Override
|
||||
protected boolean doSend(Message<?> message, long timeout) {
|
||||
@@ -139,10 +139,10 @@ public class LocalMessageBusTests extends AbstractMessageBusTests {
|
||||
assertNotSame(Thread.currentThread(), tapThread.get());
|
||||
}
|
||||
|
||||
private void verifyPayloadConversion(final Object expectedValue, final LocalMessageBus bus) {
|
||||
private void verifyPayloadConversion(final Object expectedValue, final LocalMessageChannelBinder binder) {
|
||||
DirectChannel myChannel = new DirectChannel();
|
||||
bus.bindConsumer("in", myChannel, null);
|
||||
DirectChannel input = bus.getBean("in", DirectChannel.class);
|
||||
binder.bindConsumer("in", myChannel, null);
|
||||
DirectChannel input = binder.getBean("in", DirectChannel.class);
|
||||
assertNotNull(input);
|
||||
|
||||
final AtomicBoolean msgSent = new AtomicBoolean(false);
|
||||
@@ -3,14 +3,14 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-cloud-stream-binding-rabbit</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>spring-cloud-stream-binding-rabbit</name>
|
||||
<description>RabbitMQ binding implementation</description>
|
||||
<name>spring-cloud-stream-binder-rabbit</name>
|
||||
<description>RabbitMQ binder implementation</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-bindings-parent</artifactId>
|
||||
<artifactId>spring-cloud-stream-binders-parent</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-spi</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-test</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-test</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -16,7 +16,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.rabbit;
|
||||
package org.springframework.cloud.stream.binder.rabbit;
|
||||
|
||||
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
|
||||
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
|
||||
@@ -30,7 +30,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
/**
|
||||
* Configures the connection factory used by the rabbit message bus.
|
||||
* Configures the connection factory used by the rabbit binder.
|
||||
*
|
||||
* @author Eric Bottard
|
||||
* @author Gary Russell
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.rabbit;
|
||||
package org.springframework.cloud.stream.binder.rabbit;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
@@ -35,7 +35,7 @@ import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import org.springframework.xd.dirt.integration.bus.RabbitManagementUtils;
|
||||
import org.springframework.cloud.stream.binder.RabbitManagementUtils;
|
||||
|
||||
|
||||
/**
|
||||
@@ -13,7 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.rabbit;
|
||||
package org.springframework.cloud.stream.binder.rabbit;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
@@ -26,80 +26,54 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import org.springframework.xd.dirt.integration.bus.BusCleaner;
|
||||
import org.springframework.xd.dirt.integration.bus.BusUtils;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageBusSupport;
|
||||
import org.springframework.xd.dirt.integration.bus.RabbitAdminException;
|
||||
import org.springframework.xd.dirt.integration.bus.RabbitManagementUtils;
|
||||
import org.springframework.cloud.stream.binder.BinderCleaner;
|
||||
import org.springframework.cloud.stream.binder.BinderUtils;
|
||||
import org.springframework.cloud.stream.binder.MessageChannelBinderSupport;
|
||||
import org.springframework.cloud.stream.binder.RabbitAdminException;
|
||||
import org.springframework.cloud.stream.binder.RabbitManagementUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of {@link org.springframework.xd.dirt.integration.bus.BusCleaner} for the {@code RabbitMessageBus}.
|
||||
* Implementation of {@link org.springframework.cloud.stream.binder.BinderCleaner} for the {@code RabbitBinder}.
|
||||
* @author Gary Russell
|
||||
* @author David Turanski
|
||||
* @since 1.2
|
||||
*/
|
||||
public class RabbitBusCleaner implements BusCleaner {
|
||||
public class RabbitBinderCleaner implements BinderCleaner {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(RabbitBusCleaner.class);
|
||||
private final static Logger logger = LoggerFactory.getLogger(RabbitBinderCleaner.class);
|
||||
|
||||
public static final String BINDER_PREFIX = "binder.rabbit.";
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> clean(String entity, boolean isJob) {
|
||||
return clean("http://localhost:15672", "guest", "guest", "/", "xdbus.", entity, isJob);
|
||||
return clean("http://localhost:15672", "guest", "guest", "/", BINDER_PREFIX , entity, isJob);
|
||||
}
|
||||
|
||||
public Map<String, List<String>> clean(String adminUri, String user, String pw, String vhost,
|
||||
String busPrefix, String entity, boolean isJob) {
|
||||
String binderPrefix, String entity, boolean isJob) {
|
||||
return doClean(
|
||||
adminUri == null ? "http://localhost:15672" : adminUri,
|
||||
user == null ? "guest" : user,
|
||||
pw == null ? "guest" : pw,
|
||||
vhost == null ? "/" : vhost,
|
||||
busPrefix == null ? "xdbus." : busPrefix,
|
||||
//TODO: Change prefix
|
||||
binderPrefix == null ? BINDER_PREFIX : binderPrefix,
|
||||
entity, isJob);
|
||||
}
|
||||
|
||||
private Map<String, List<String>> doClean(String adminUri, String user, String pw, String vhost,
|
||||
String busPrefix, String entity, boolean isJob) {
|
||||
String binderPrefix, String entity, boolean isJob) {
|
||||
RestTemplate restTemplate = RabbitManagementUtils.buildRestTemplate(adminUri, user, pw);
|
||||
List<String> removedQueues = isJob
|
||||
? null//findJobQueues(adminUri, vhost, busPrefix, entity, restTemplate)
|
||||
: findStreamQueues(adminUri, vhost, busPrefix, entity, restTemplate);
|
||||
? null
|
||||
: findStreamQueues(adminUri, vhost, binderPrefix, entity, restTemplate);
|
||||
ExchangeCandidateCallback callback = null;
|
||||
if (isJob) {
|
||||
// String pattern;
|
||||
// if (entity.endsWith("*")) {
|
||||
// pattern = entity.substring(0, entity.length() - 1) + "[^.]*";
|
||||
// }
|
||||
// else {
|
||||
// pattern = entity;
|
||||
// }
|
||||
// Collection<String> exchangeNames = JobEventsListenerPlugin.getEventListenerChannels(pattern).values();
|
||||
// final Set<Pattern> jobExchanges = new HashSet<>();
|
||||
// for (String exchange : exchangeNames) {
|
||||
// jobExchanges.add(Pattern.compile(MessageBusSupport.applyPrefix(busPrefix,
|
||||
// MessageBusSupport.applyPubSub(exchange))));
|
||||
// }
|
||||
// jobExchanges.add(Pattern.compile(MessageBusSupport.applyPrefix(busPrefix, MessageBusSupport.applyPubSub(
|
||||
// JobEventsListenerPlugin.getEventListenerChannelName(pattern)))));
|
||||
// callback = new ExchangeCandidateCallback() {
|
||||
//
|
||||
// @Override
|
||||
// public boolean isCandidate(String exchangeName) {
|
||||
// for (Pattern pattern : jobExchanges) {
|
||||
// Matcher matcher = pattern.matcher(exchangeName);
|
||||
// if (matcher.matches()) {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// };
|
||||
}
|
||||
else {
|
||||
final String tapPrefix = adjustPrefix(MessageBusSupport.applyPrefix(busPrefix,
|
||||
MessageBusSupport.applyPubSub(BusUtils.constructTapPrefix(entity))));
|
||||
final String tapPrefix = adjustPrefix(MessageChannelBinderSupport.applyPrefix(binderPrefix,
|
||||
MessageChannelBinderSupport.applyPubSub(BinderUtils.constructTapPrefix(entity))));
|
||||
callback = new ExchangeCandidateCallback() {
|
||||
|
||||
@Override
|
||||
@@ -108,7 +82,7 @@ public class RabbitBusCleaner implements BusCleaner {
|
||||
}
|
||||
};
|
||||
}
|
||||
List<String> removedExchanges = findExchanges(adminUri, vhost, busPrefix, entity, restTemplate, callback);
|
||||
List<String> removedExchanges = findExchanges(adminUri, vhost, binderPrefix, entity, restTemplate, callback);
|
||||
// Delete the queues in reverse order to enable re-running after a partial success.
|
||||
// The queue search above starts with 0 and terminates on a not found.
|
||||
for (int i = removedQueues.size() - 1; i >= 0; i--) {
|
||||
@@ -141,9 +115,9 @@ public class RabbitBusCleaner implements BusCleaner {
|
||||
return results;
|
||||
}
|
||||
|
||||
private List<String> findStreamQueues(String adminUri, String vhost, String busPrefix, String stream,
|
||||
private List<String> findStreamQueues(String adminUri, String vhost, String binderPrefix, String stream,
|
||||
RestTemplate restTemplate) {
|
||||
String queueNamePrefix = adjustPrefix(MessageBusSupport.applyPrefix(busPrefix, stream));
|
||||
String queueNamePrefix = adjustPrefix(MessageChannelBinderSupport.applyPrefix(binderPrefix, stream));
|
||||
List<Map<String, Object>> queues = listAllQueues(adminUri, vhost, restTemplate);
|
||||
List<String> removedQueues = new ArrayList<>();
|
||||
for (Map<String, Object> queue : queues) {
|
||||
@@ -156,37 +130,6 @@ public class RabbitBusCleaner implements BusCleaner {
|
||||
return removedQueues;
|
||||
}
|
||||
|
||||
// private List<String> findJobQueues(String adminUri, String vhost, String busPrefix, String job,
|
||||
// RestTemplate restTemplate) {
|
||||
// List<String> removedQueues = new ArrayList<>();
|
||||
// String jobQueueName = MessageBusSupport.applyPrefix(busPrefix,
|
||||
// AbstractJobPlugin.getJobChannelName(job));
|
||||
// String jobRequestsQueuePrefix = adjustPrefix(MessageBusSupport.applyPrefix(busPrefix,
|
||||
// AbstractJobPlugin.getJobChannelName(job)));
|
||||
// List<Map<String, Object>> queues = listAllQueues(adminUri, vhost, restTemplate);
|
||||
// for (Map<String, Object> queue : queues) {
|
||||
// String queueName = (String) queue.get("name");
|
||||
// if (job.endsWith("*")) {
|
||||
// if (queueName.startsWith(jobQueueName.substring(0, jobQueueName.length() - 1))) {
|
||||
// checkNoConsumers(queueName, queue);
|
||||
// removedQueues.add(queueName);
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// if (queueName.equals(jobQueueName)) {
|
||||
// checkNoConsumers(queueName, queue);
|
||||
// removedQueues.add(queueName);
|
||||
// }
|
||||
// else if (queueName.startsWith(jobRequestsQueuePrefix)
|
||||
// && queueName.endsWith(MessageBusSupport.applyRequests(""))) {
|
||||
// checkNoConsumers(queueName, queue);
|
||||
// removedQueues.add(queueName);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return removedQueues;
|
||||
// }
|
||||
|
||||
private List<Map<String, Object>> listAllQueues(String adminUri, String vhost, RestTemplate restTemplate) {
|
||||
URI uri = UriComponentsBuilder.fromUriString(adminUri + "/api")
|
||||
.pathSegment("queues", "{vhost}")
|
||||
@@ -201,7 +144,7 @@ public class RabbitBusCleaner implements BusCleaner {
|
||||
return prefix.substring(0, prefix.length() - 1);
|
||||
}
|
||||
else {
|
||||
return prefix + BusUtils.GROUP_INDEX_DELIMITER;
|
||||
return prefix + BinderUtils.GROUP_INDEX_DELIMITER;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,7 +155,7 @@ public class RabbitBusCleaner implements BusCleaner {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<String> findExchanges(String adminUri, String vhost, String busPrefix, String entity,
|
||||
private List<String> findExchanges(String adminUri, String vhost, String binderPrefix, String entity,
|
||||
RestTemplate restTemplate, ExchangeCandidateCallback callback) {
|
||||
List<String> removedExchanges = new ArrayList<>();
|
||||
URI uri = UriComponentsBuilder.fromUriString(adminUri + "/api")
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.rabbit;
|
||||
package org.springframework.cloud.stream.binder.rabbit;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
@@ -84,13 +84,12 @@ import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.xd.dirt.integration.bus.AbstractBusPropertiesAccessor;
|
||||
import org.springframework.xd.dirt.integration.bus.Binding;
|
||||
import org.springframework.xd.dirt.integration.bus.BusProperties;
|
||||
import org.springframework.xd.dirt.integration.bus.BusUtils;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageBus;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageBusSupport;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageValues;
|
||||
import org.springframework.cloud.stream.binder.AbstractBinderPropertiesAccessor;
|
||||
import org.springframework.cloud.stream.binder.BinderUtils;
|
||||
import org.springframework.cloud.stream.binder.Binding;
|
||||
import org.springframework.cloud.stream.binder.BinderProperties;
|
||||
import org.springframework.cloud.stream.binder.MessageChannelBinderSupport;
|
||||
import org.springframework.cloud.stream.binder.MessageValues;
|
||||
import org.springframework.xd.dirt.integration.bus.serializer.MultiTypeCodec;
|
||||
|
||||
import com.rabbitmq.client.AMQP;
|
||||
@@ -98,7 +97,7 @@ import com.rabbitmq.client.Channel;
|
||||
import com.rabbitmq.client.Envelope;
|
||||
|
||||
/**
|
||||
* A {@link MessageBus} implementation backed by RabbitMQ.
|
||||
* A {@link org.springframework.cloud.stream.binder.Binder} implementation backed by RabbitMQ.
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
* @author Jennifer Hickey
|
||||
@@ -106,7 +105,7 @@ import com.rabbitmq.client.Envelope;
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @author David Turanski
|
||||
*/
|
||||
public class RabbitMessageBus extends MessageBusSupport implements DisposableBean {
|
||||
public class RabbitMessageChannelBinder extends MessageChannelBinderSupport implements DisposableBean {
|
||||
|
||||
private static final AcknowledgeMode DEFAULT_ACKNOWLEDGE_MODE = AcknowledgeMode.AUTO;
|
||||
|
||||
@@ -118,7 +117,7 @@ public class RabbitMessageBus extends MessageBusSupport implements DisposableBea
|
||||
|
||||
private static final int DEFAULT_PREFETCH_COUNT = 1;
|
||||
|
||||
private static final String DEFAULT_RABBIT_PREFIX = "xdbus.";
|
||||
private static final String DEFAULT_RABBIT_PREFIX = "binder.rabbit.";
|
||||
|
||||
private static final int DEFAULT_TX_SIZE = 1;
|
||||
|
||||
@@ -130,7 +129,7 @@ public class RabbitMessageBus extends MessageBusSupport implements DisposableBea
|
||||
|
||||
private static final Set<Object> RABBIT_CONSUMER_PROPERTIES = new HashSet<Object>(Arrays.asList(new String[] {
|
||||
|
||||
BusProperties.MAX_CONCURRENCY,
|
||||
BinderProperties.MAX_CONCURRENCY,
|
||||
RabbitPropertiesAccessor.ACK_MODE,
|
||||
RabbitPropertiesAccessor.PREFETCH,
|
||||
RabbitPropertiesAccessor.PREFIX,
|
||||
@@ -153,7 +152,7 @@ public class RabbitMessageBus extends MessageBusSupport implements DisposableBea
|
||||
|
||||
private static final Set<Object> SUPPORTED_PUBSUB_CONSUMER_PROPERTIES = new SetBuilder()
|
||||
.addAll(SUPPORTED_BASIC_CONSUMER_PROPERTIES)
|
||||
.add(BusProperties.DURABLE)
|
||||
.add(BinderProperties.DURABLE)
|
||||
.build();
|
||||
|
||||
/**
|
||||
@@ -161,7 +160,7 @@ public class RabbitMessageBus extends MessageBusSupport implements DisposableBea
|
||||
*/
|
||||
private static final Set<Object> SUPPORTED_NAMED_CONSUMER_PROPERTIES = new SetBuilder()
|
||||
.addAll(SUPPORTED_BASIC_CONSUMER_PROPERTIES)
|
||||
.add(BusProperties.CONCURRENCY)
|
||||
.add(BinderProperties.CONCURRENCY)
|
||||
.build();
|
||||
|
||||
/**
|
||||
@@ -169,8 +168,8 @@ public class RabbitMessageBus extends MessageBusSupport implements DisposableBea
|
||||
*/
|
||||
private static final Set<Object> SUPPORTED_CONSUMER_PROPERTIES = new SetBuilder()
|
||||
.addAll(SUPPORTED_BASIC_CONSUMER_PROPERTIES)
|
||||
.add(BusProperties.CONCURRENCY)
|
||||
.add(BusProperties.PARTITION_INDEX)
|
||||
.add(BinderProperties.CONCURRENCY)
|
||||
.add(BinderProperties.PARTITION_INDEX)
|
||||
.build();
|
||||
|
||||
/**
|
||||
@@ -179,7 +178,7 @@ public class RabbitMessageBus extends MessageBusSupport implements DisposableBea
|
||||
private static final Set<Object> SUPPORTED_REPLYING_CONSUMER_PROPERTIES = new SetBuilder()
|
||||
// request
|
||||
.addAll(SUPPORTED_BASIC_CONSUMER_PROPERTIES)
|
||||
.add(BusProperties.CONCURRENCY)
|
||||
.add(BinderProperties.CONCURRENCY)
|
||||
// reply
|
||||
.add(RabbitPropertiesAccessor.REPLY_HEADER_PATTERNS)
|
||||
.add(RabbitPropertiesAccessor.DELIVERY_MODE)
|
||||
@@ -193,7 +192,7 @@ public class RabbitMessageBus extends MessageBusSupport implements DisposableBea
|
||||
.add(RabbitPropertiesAccessor.DELIVERY_MODE)
|
||||
.add(RabbitPropertiesAccessor.PREFIX)
|
||||
.add(RabbitPropertiesAccessor.REQUEST_HEADER_PATTERNS)
|
||||
.add(BusProperties.COMPRESS)
|
||||
.add(BinderProperties.COMPRESS)
|
||||
.build();
|
||||
|
||||
private static final Set<Object> SUPPORTED_PUBSUB_PRODUCER_PROPERTIES = new SetBuilder()
|
||||
@@ -214,7 +213,7 @@ public class RabbitMessageBus extends MessageBusSupport implements DisposableBea
|
||||
private static final Set<Object> SUPPORTED_PRODUCER_PROPERTIES = new SetBuilder()
|
||||
.addAll(PRODUCER_PARTITIONING_PROPERTIES)
|
||||
.addAll(SUPPORTED_BASIC_PRODUCER_PROPERTIES)
|
||||
.add(BusProperties.DIRECT_BINDING_ALLOWED)
|
||||
.add(BinderProperties.DIRECT_BINDING_ALLOWED)
|
||||
.addAll(PRODUCER_BATCHING_BASIC_PROPERTIES)
|
||||
.addAll(PRODUCER_BATCHING_ADVANCED_PROPERTIES)
|
||||
.build();
|
||||
@@ -227,7 +226,7 @@ public class RabbitMessageBus extends MessageBusSupport implements DisposableBea
|
||||
.addAll(SUPPORTED_BASIC_PRODUCER_PROPERTIES)
|
||||
// reply
|
||||
.addAll(SUPPORTED_BASIC_CONSUMER_PROPERTIES)
|
||||
.add(BusProperties.CONCURRENCY)
|
||||
.add(BinderProperties.CONCURRENCY)
|
||||
.add(RabbitPropertiesAccessor.REPLY_HEADER_PATTERNS)
|
||||
.build();
|
||||
|
||||
@@ -303,7 +302,7 @@ public class RabbitMessageBus extends MessageBusSupport implements DisposableBea
|
||||
|
||||
private volatile boolean clustered;
|
||||
|
||||
public RabbitMessageBus(ConnectionFactory connectionFactory, MultiTypeCodec<Object> codec) {
|
||||
public RabbitMessageChannelBinder(ConnectionFactory connectionFactory, MultiTypeCodec<Object> codec) {
|
||||
Assert.notNull(connectionFactory, "connectionFactory must not be null");
|
||||
Assert.notNull(codec, "codec must not be null");
|
||||
this.connectionFactory = connectionFactory;
|
||||
@@ -353,7 +352,7 @@ public class RabbitMessageBus extends MessageBusSupport implements DisposableBea
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bus's default max consumers; can be overridden by consumer.maxConcurrency. Values less than 'concurrency'
|
||||
* Set the binder's default max consumers; can be overridden by consumer.maxConcurrency. Values less than 'concurrency'
|
||||
* will be coerced to be equal to concurrency.
|
||||
* @param defaultMaxConcurrency The default max concurrency.
|
||||
*/
|
||||
@@ -464,7 +463,7 @@ public class RabbitMessageBus extends MessageBusSupport implements DisposableBea
|
||||
|
||||
@Override
|
||||
public void bindPubSubConsumer(String name, MessageChannel moduleInputChannel, Properties properties) {
|
||||
String exchangeName = BusUtils.removeGroupFromPubSub(name);
|
||||
String exchangeName = BinderUtils.removeGroupFromPubSub(name);
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("declaring pubsub for inbound: " + name + ", bound to: " + exchangeName);
|
||||
}
|
||||
@@ -550,7 +549,7 @@ public class RabbitMessageBus extends MessageBusSupport implements DisposableBea
|
||||
listenerContainer.setAdviceChain(new Advice[] { retryInterceptor });
|
||||
}
|
||||
listenerContainer.setAfterReceivePostProcessors(this.decompressingPostProcessor);
|
||||
listenerContainer.setMessagePropertiesConverter(RabbitMessageBus.inboundMessagePropertiesConverter);
|
||||
listenerContainer.setMessagePropertiesConverter(RabbitMessageChannelBinder.inboundMessagePropertiesConverter);
|
||||
listenerContainer.afterPropertiesSet();
|
||||
AmqpInboundChannelAdapter adapter = new AmqpInboundChannelAdapter(listenerContainer);
|
||||
adapter.setBeanFactory(this.getBeanFactory());
|
||||
@@ -768,7 +767,7 @@ public class RabbitMessageBus extends MessageBusSupport implements DisposableBea
|
||||
channel.exchangeDeclarePassive(exchange.getName());
|
||||
}
|
||||
catch (IOException e) {
|
||||
RabbitMessageBus.this.rabbitAdmin.declareExchange(exchange);
|
||||
RabbitMessageChannelBinder.this.rabbitAdmin.declareExchange(exchange);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -874,7 +873,7 @@ public class RabbitMessageBus extends MessageBusSupport implements DisposableBea
|
||||
this.delegate = delegate;
|
||||
this.replyTo = replyTo;
|
||||
this.partitioningMetadata = new PartitioningMetadata(properties, properties.getNextModuleCount());
|
||||
this.setBeanFactory(RabbitMessageBus.this.getBeanFactory());
|
||||
this.setBeanFactory(RabbitMessageChannelBinder.this.getBeanFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -921,7 +920,7 @@ public class RabbitMessageBus extends MessageBusSupport implements DisposableBea
|
||||
|
||||
public ReceivingHandler() {
|
||||
super();
|
||||
this.setBeanFactory(RabbitMessageBus.this.getBeanFactory());
|
||||
this.setBeanFactory(RabbitMessageChannelBinder.this.getBeanFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -941,10 +940,10 @@ public class RabbitMessageBus extends MessageBusSupport implements DisposableBea
|
||||
}
|
||||
|
||||
/**
|
||||
* Property accessor for the RabbitMessageBus. Refer to the Spring-AMQP documentation for information on the
|
||||
* Property accessor for the RabbitBinder. Refer to the Spring-AMQP documentation for information on the
|
||||
* specific properties.
|
||||
*/
|
||||
private static class RabbitPropertiesAccessor extends AbstractBusPropertiesAccessor {
|
||||
private static class RabbitPropertiesAccessor extends AbstractBinderPropertiesAccessor {
|
||||
|
||||
/**
|
||||
* The acknowledge mode.
|
||||
@@ -992,12 +991,12 @@ public class RabbitMessageBus extends MessageBusSupport implements DisposableBea
|
||||
private static final String TX_SIZE = "txSize";
|
||||
|
||||
/**
|
||||
* Whether to automatically declare the DLQ and bind it to the bus DLX.
|
||||
* Whether to automatically declare the DLQ and bind it to the binder DLX.
|
||||
*/
|
||||
private static final String AUTO_BIND_DLQ = "autoBindDLQ";
|
||||
|
||||
/**
|
||||
* Whether to automatically declare the DLQ and bind it to the bus DLX.
|
||||
* Whether to automatically declare the DLQ and bind it to the binder DLX.
|
||||
*/
|
||||
private static final String REPUBLISH_TO_DLQ = "republishToDLQ";
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* This package contains an implementation of the {@link org.springframework.cloud.stream.binder.Binder} for RabbitMQ.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.stream.binder.rabbit;
|
||||
@@ -5,9 +5,9 @@
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<bean class="org.springframework.xd.dirt.integration.rabbit.ConnectionFactorySettings" />
|
||||
<bean class="org.springframework.cloud.stream.binder.rabbit.ConnectionFactorySettings" />
|
||||
|
||||
<bean id="messageBus" class="org.springframework.xd.dirt.integration.rabbit.RabbitMessageBus">
|
||||
<bean id="messageBus" class="org.springframework.cloud.stream.binder.rabbit.RabbitMessageChannelBinder">
|
||||
<constructor-arg ref="rabbitConnectionFactory" />
|
||||
<constructor-arg ref="codec"/>
|
||||
<property name="defaultAcknowledgeMode" value="#{T(org.springframework.amqp.core.AcknowledgeMode).${xd.messagebus.rabbit.default.ackMode}}" />
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.rabbit;
|
||||
package org.springframework.cloud.stream.binder.rabbit;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.rabbit;
|
||||
package org.springframework.cloud.stream.binder.rabbit;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
@@ -14,13 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.rabbit;
|
||||
package org.springframework.cloud.stream.binder.rabbit;
|
||||
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.xd.test.AbstractExternalResourceTestSupport;
|
||||
import org.springframework.cloud.stream.binder.AbstractExternalResourceTestSupport;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.rabbit;
|
||||
package org.springframework.cloud.stream.binder.rabbit;
|
||||
|
||||
|
||||
import java.net.URI;
|
||||
@@ -37,10 +37,10 @@ import org.springframework.amqp.rabbit.core.RabbitAdmin;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import org.springframework.xd.dirt.integration.bus.BusUtils;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageBusSupport;
|
||||
import org.springframework.xd.dirt.integration.bus.RabbitAdminException;
|
||||
import org.springframework.xd.dirt.integration.bus.RabbitManagementUtils;
|
||||
import org.springframework.cloud.stream.binder.BinderUtils;
|
||||
import org.springframework.cloud.stream.binder.MessageChannelBinderSupport;
|
||||
import org.springframework.cloud.stream.binder.RabbitAdminException;
|
||||
import org.springframework.cloud.stream.binder.RabbitManagementUtils;
|
||||
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -52,9 +52,9 @@ import static org.junit.Assert.fail;
|
||||
* @author Gary Russell
|
||||
* @since 1.2
|
||||
*/
|
||||
public class RabbitBusCleanerTests {
|
||||
public class RabbitBinderCleanerTests {
|
||||
|
||||
private static final String XDBUS_PREFIX = "xdbus.";
|
||||
private static final String BINDER_PREFIX = "binder.rabbit.";
|
||||
|
||||
@Rule
|
||||
public RabbitAdminTestSupport adminTest = new RabbitAdminTestSupport();
|
||||
@@ -64,17 +64,17 @@ public class RabbitBusCleanerTests {
|
||||
|
||||
@Test
|
||||
public void testCleanStream() {
|
||||
final RabbitBusCleaner cleaner = new RabbitBusCleaner();
|
||||
final RabbitBinderCleaner cleaner = new RabbitBinderCleaner();
|
||||
final RestTemplate template = RabbitManagementUtils.buildRestTemplate("http://localhost:15672", "guest",
|
||||
"guest");
|
||||
final String stream1 = UUID.randomUUID().toString();
|
||||
String stream2 = stream1 + "-1";
|
||||
String firstQueue = null;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
String queue1Name = MessageBusSupport.applyPrefix(XDBUS_PREFIX,
|
||||
BusUtils.constructPipeName(stream1, i));
|
||||
String queue2Name = MessageBusSupport.applyPrefix(XDBUS_PREFIX,
|
||||
BusUtils.constructPipeName(stream2, i));
|
||||
String queue1Name = MessageChannelBinderSupport.applyPrefix(BINDER_PREFIX,
|
||||
BinderUtils.constructPipeName(stream1, i));
|
||||
String queue2Name = MessageChannelBinderSupport.applyPrefix(BINDER_PREFIX,
|
||||
BinderUtils.constructPipeName(stream2, i));
|
||||
if (firstQueue == null) {
|
||||
firstQueue = queue1Name;
|
||||
}
|
||||
@@ -90,27 +90,27 @@ public class RabbitBusCleanerTests {
|
||||
template.put(uri, new AmqpQueue(false, true));
|
||||
uri = UriComponentsBuilder.fromUriString("http://localhost:15672/api/queues")
|
||||
.pathSegment("{vhost}", "{queue}")
|
||||
.buildAndExpand("/", MessageBusSupport.constructDLQName(queue1Name)).encode().toUri();
|
||||
.buildAndExpand("/", MessageChannelBinderSupport.constructDLQName(queue1Name)).encode().toUri();
|
||||
template.put(uri, new AmqpQueue(false, true));
|
||||
}
|
||||
CachingConnectionFactory connectionFactory = test.getResource();
|
||||
RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
|
||||
final FanoutExchange fanout1 = new FanoutExchange(
|
||||
MessageBusSupport.applyPrefix(XDBUS_PREFIX, MessageBusSupport.applyPubSub(
|
||||
BusUtils.constructTapPrefix(stream1) + ".foo.bar")));
|
||||
MessageChannelBinderSupport.applyPrefix(BINDER_PREFIX, MessageChannelBinderSupport.applyPubSub(
|
||||
BinderUtils.constructTapPrefix(stream1) + ".foo.bar")));
|
||||
rabbitAdmin.declareExchange(fanout1);
|
||||
rabbitAdmin.declareBinding(BindingBuilder.bind(new Queue(firstQueue)).to(fanout1));
|
||||
final FanoutExchange fanout2 = new FanoutExchange(
|
||||
MessageBusSupport.applyPrefix(XDBUS_PREFIX, MessageBusSupport.applyPubSub(
|
||||
BusUtils.constructTapPrefix(stream2) + ".foo.bar")));
|
||||
MessageChannelBinderSupport.applyPrefix(BINDER_PREFIX, MessageChannelBinderSupport.applyPubSub(
|
||||
BinderUtils.constructTapPrefix(stream2) + ".foo.bar")));
|
||||
rabbitAdmin.declareExchange(fanout2);
|
||||
rabbitAdmin.declareBinding(BindingBuilder.bind(new Queue(firstQueue)).to(fanout2));
|
||||
new RabbitTemplate(connectionFactory).execute(new ChannelCallback<Void>() {
|
||||
|
||||
@Override
|
||||
public Void doInRabbit(Channel channel) throws Exception {
|
||||
String queueName = MessageBusSupport.applyPrefix(XDBUS_PREFIX,
|
||||
BusUtils.constructPipeName(stream1, 4));
|
||||
String queueName = MessageChannelBinderSupport.applyPrefix(BINDER_PREFIX,
|
||||
BinderUtils.constructPipeName(stream1, 4));
|
||||
String consumerTag = channel.basicConsume(queueName, new DefaultConsumer(channel));
|
||||
try {
|
||||
waitForConsumerStateNot(queueName, 0);
|
||||
@@ -159,8 +159,8 @@ public class RabbitBusCleanerTests {
|
||||
// should *not* clean stream2
|
||||
assertEquals(10, cleanedQueues.size());
|
||||
for (int i = 0; i < 5; i++) {
|
||||
assertEquals(XDBUS_PREFIX + stream1 + "." + i, cleanedQueues.get(i * 2));
|
||||
assertEquals(XDBUS_PREFIX + stream1 + "." + i + ".dlq", cleanedQueues.get(i * 2 + 1));
|
||||
assertEquals(BINDER_PREFIX + stream1 + "." + i, cleanedQueues.get(i * 2));
|
||||
assertEquals(BINDER_PREFIX + stream1 + "." + i + ".dlq", cleanedQueues.get(i * 2 + 1));
|
||||
}
|
||||
List<String> cleanedExchanges = cleanedMap.get("exchanges");
|
||||
assertEquals(1, cleanedExchanges.size());
|
||||
@@ -172,7 +172,7 @@ public class RabbitBusCleanerTests {
|
||||
cleanedQueues = cleanedMap.get("queues");
|
||||
assertEquals(5, cleanedQueues.size());
|
||||
for (int i = 0; i < 5; i++) {
|
||||
assertEquals(XDBUS_PREFIX + stream2 + "." + i, cleanedQueues.get(i));
|
||||
assertEquals(BINDER_PREFIX + stream2 + "." + i, cleanedQueues.get(i));
|
||||
}
|
||||
cleanedExchanges = cleanedMap.get("exchanges");
|
||||
assertEquals(1, cleanedExchanges.size());
|
||||
@@ -14,22 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.rabbit;
|
||||
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
package org.springframework.cloud.stream.binder.rabbit;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@@ -56,6 +41,11 @@ import org.springframework.amqp.support.AmqpHeaders;
|
||||
import org.springframework.amqp.support.postprocessor.DelegatingDecompressingPostProcessor;
|
||||
import org.springframework.amqp.utils.test.TestUtils;
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.cloud.stream.binder.Binder;
|
||||
import org.springframework.cloud.stream.binder.BinderProperties;
|
||||
import org.springframework.cloud.stream.binder.Binding;
|
||||
import org.springframework.cloud.stream.binder.PartitionCapableBinderTests;
|
||||
import org.springframework.cloud.stream.binder.Spy;
|
||||
import org.springframework.expression.spel.standard.SpelExpression;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
@@ -66,27 +56,43 @@ import org.springframework.messaging.MessageHandler;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.xd.dirt.integration.bus.Binding;
|
||||
import org.springframework.xd.dirt.integration.bus.BusProperties;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageBus;
|
||||
import org.springframework.xd.dirt.integration.bus.PartitionCapableBusTests;
|
||||
import org.springframework.xd.dirt.integration.bus.Spy;
|
||||
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
public class RabbitBinderTests extends PartitionCapableBinderTests {
|
||||
|
||||
private final String CLASS_UNDER_TEST_NAME = RabbitMessageChannelBinder.class.getSimpleName();
|
||||
|
||||
public static final String BINDER_PREFIX = "binder.rabbit.";
|
||||
|
||||
public static final String TEST_PREFIX = "bindertest.";
|
||||
|
||||
@Rule
|
||||
public RabbitTestSupport rabbitAvailableRule = new RabbitTestSupport();
|
||||
|
||||
@Override
|
||||
protected MessageBus getMessageBus() {
|
||||
if (testMessageBus == null) {
|
||||
testMessageBus = new RabbitTestMessageBus(rabbitAvailableRule.getResource(), getCodec());
|
||||
protected Binder getBinder() {
|
||||
if (testBinder == null) {
|
||||
testBinder = new RabbitTestBinder(rabbitAvailableRule.getResource(), getCodec());
|
||||
}
|
||||
return testMessageBus;
|
||||
return testBinder;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,12 +102,13 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
|
||||
@Test
|
||||
public void testSendAndReceiveBad() throws Exception {
|
||||
MessageBus messageBus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
DirectChannel moduleOutputChannel = new DirectChannel();
|
||||
DirectChannel moduleInputChannel = new DirectChannel();
|
||||
messageBus.bindProducer("bad.0", moduleOutputChannel, null);
|
||||
messageBus.bindConsumer("bad.0", moduleInputChannel, null);
|
||||
Message<?> message = MessageBuilder.withPayload("bad").setHeader(MessageHeaders.CONTENT_TYPE, "foo/bar").build();
|
||||
binder.bindProducer("bad.0", moduleOutputChannel, null);
|
||||
binder.bindConsumer("bad.0", moduleInputChannel, null);
|
||||
Message<?> message = MessageBuilder.withPayload("bad").setHeader(MessageHeaders.CONTENT_TYPE,
|
||||
"foo/bar").build();
|
||||
final CountDownLatch latch = new CountDownLatch(3);
|
||||
moduleInputChannel.subscribe(new MessageHandler() {
|
||||
|
||||
@@ -113,24 +120,24 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
});
|
||||
moduleOutputChannel.send(message);
|
||||
assertTrue(latch.await(10, TimeUnit.SECONDS));
|
||||
messageBus.unbindConsumers("bad.0");
|
||||
messageBus.unbindProducers("bad.0");
|
||||
binder.unbindConsumers("bad.0");
|
||||
binder.unbindProducers("bad.0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConsumerProperties() throws Exception {
|
||||
MessageBus bus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
Properties properties = new Properties();
|
||||
properties.put("transacted", "true"); // test transacted with defaults; not allowed with ackmode NONE
|
||||
bus.bindConsumer("props.0", new DirectChannel(), properties);
|
||||
binder.bindConsumer("props.0", new DirectChannel(), properties);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(bus, "messageBus.bindings", List.class);
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(binder, "binder.bindings", List.class);
|
||||
assertEquals(1, bindings.size());
|
||||
AbstractEndpoint endpoint = bindings.get(0).getEndpoint();
|
||||
SimpleMessageListenerContainer container = TestUtils.getPropertyValue(endpoint, "messageListenerContainer",
|
||||
SimpleMessageListenerContainer.class);
|
||||
assertEquals(AcknowledgeMode.AUTO, container.getAcknowledgeMode());
|
||||
assertEquals("xdbus.props.0", container.getQueueNames()[0]);
|
||||
assertEquals(BINDER_PREFIX + "props.0", container.getQueueNames()[0]);
|
||||
assertTrue(TestUtils.getPropertyValue(container, "transactional", Boolean.class));
|
||||
assertEquals(1, TestUtils.getPropertyValue(container, "concurrentConsumers"));
|
||||
assertNull(TestUtils.getPropertyValue(container, "maxConcurrentConsumers"));
|
||||
@@ -142,7 +149,7 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
assertEquals(1000L, TestUtils.getPropertyValue(retry, "retryOperations.backOffPolicy.initialInterval"));
|
||||
assertEquals(10000L, TestUtils.getPropertyValue(retry, "retryOperations.backOffPolicy.maxInterval"));
|
||||
assertEquals(2.0, TestUtils.getPropertyValue(retry, "retryOperations.backOffPolicy.multiplier"));
|
||||
bus.unbindConsumers("props.0");
|
||||
binder.unbindConsumers("props.0");
|
||||
assertEquals(0, bindings.size());
|
||||
|
||||
properties = new Properties();
|
||||
@@ -159,10 +166,10 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
properties.put("requeue", "false");
|
||||
properties.put("txSize", "10");
|
||||
properties.put("partitionIndex", 0);
|
||||
bus.bindConsumer("props.0", new DirectChannel(), properties);
|
||||
binder.bindConsumer("props.0", new DirectChannel(), properties);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Binding> bindingsNow = TestUtils.getPropertyValue(bus, "messageBus.bindings", List.class);
|
||||
List<Binding> bindingsNow = TestUtils.getPropertyValue(binder, "binder.bindings", List.class);
|
||||
assertEquals(1, bindingsNow.size());
|
||||
endpoint = bindingsNow.get(0).getEndpoint();
|
||||
container = verifyContainer(endpoint);
|
||||
@@ -170,45 +177,45 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
assertEquals("foo.props.0", container.getQueueNames()[0]);
|
||||
|
||||
try {
|
||||
bus.bindPubSubConsumer("dummy", null, properties);
|
||||
binder.bindPubSubConsumer("dummy", null, properties);
|
||||
fail("Expected exception");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), allOf(
|
||||
containsString("RabbitMessageBus does not support consumer properties: "),
|
||||
containsString(getClassUnderTestName() + " does not support consumer properties: "),
|
||||
containsString("partitionIndex"),
|
||||
containsString("concurrency"),
|
||||
containsString(" for dummy.")));
|
||||
}
|
||||
try {
|
||||
bus.bindConsumer("queue:dummy", null, properties);
|
||||
binder.bindConsumer("queue:dummy", null, properties);
|
||||
fail("Expected exception");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertEquals("RabbitMessageBus does not support consumer property: partitionIndex for queue:dummy.",
|
||||
assertEquals(getClassUnderTestName() + " does not support consumer property: partitionIndex for queue:dummy.",
|
||||
e.getMessage());
|
||||
}
|
||||
|
||||
bus.unbindConsumers("props.0");
|
||||
binder.unbindConsumers("props.0");
|
||||
assertEquals(0, bindingsNow.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProducerProperties() throws Exception {
|
||||
MessageBus bus = getMessageBus();
|
||||
bus.bindProducer("props.0", new DirectChannel(), null);
|
||||
Binder binder = getBinder();
|
||||
binder.bindProducer("props.0", new DirectChannel(), null);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(bus, "messageBus.bindings", List.class);
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(binder, "binder.bindings", List.class);
|
||||
assertEquals(1, bindings.size());
|
||||
AbstractEndpoint endpoint = bindings.get(0).getEndpoint();
|
||||
assertEquals("xdbus.props.0", TestUtils.getPropertyValue(endpoint, "handler.delegate.routingKey"));
|
||||
assertEquals(BINDER_PREFIX + "props.0", TestUtils.getPropertyValue(endpoint, "handler.delegate.routingKey"));
|
||||
MessageDeliveryMode mode = TestUtils.getPropertyValue(endpoint, "handler.delegate.defaultDeliveryMode",
|
||||
MessageDeliveryMode.class);
|
||||
assertEquals(MessageDeliveryMode.PERSISTENT, mode);
|
||||
List<?> requestHeaders = TestUtils.getPropertyValue(endpoint,
|
||||
"handler.delegate.headerMapper.requestHeaderMatcher.strategies", List.class);
|
||||
assertEquals(2, requestHeaders.size());
|
||||
bus.unbindProducers("props.0");
|
||||
binder.unbindProducers("props.0");
|
||||
assertEquals(0, bindings.size());
|
||||
|
||||
Properties properties = new Properties();
|
||||
@@ -219,26 +226,27 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
properties.put("partitionKeyExtractorClass", "foo");
|
||||
properties.put("partitionSelectorExpression", "0");
|
||||
properties.put("partitionSelectorClass", "foo");
|
||||
properties.put(BusProperties.NEXT_MODULE_COUNT, "1");
|
||||
properties.put(BinderProperties.NEXT_MODULE_COUNT, "1");
|
||||
|
||||
bus.bindProducer("props.0", new DirectChannel(), properties);
|
||||
binder.bindProducer("props.0", new DirectChannel(), properties);
|
||||
assertEquals(1, bindings.size());
|
||||
endpoint = bindings.get(0).getEndpoint();
|
||||
assertEquals(
|
||||
"'foo.props.0-' + headers['partition']",
|
||||
TestUtils.getPropertyValue(endpoint, "handler.delegate.routingKeyExpression", SpelExpression.class).getExpressionString());
|
||||
TestUtils.getPropertyValue(endpoint, "handler.delegate.routingKeyExpression",
|
||||
SpelExpression.class).getExpressionString());
|
||||
mode = TestUtils.getPropertyValue(endpoint, "handler.delegate.defaultDeliveryMode",
|
||||
MessageDeliveryMode.class);
|
||||
assertEquals(MessageDeliveryMode.NON_PERSISTENT, mode);
|
||||
verifyFooRequestProducer(endpoint);
|
||||
|
||||
try {
|
||||
bus.bindPubSubProducer("dummy", new DirectChannel(), properties);
|
||||
binder.bindPubSubProducer("dummy", new DirectChannel(), properties);
|
||||
fail("Expected exception");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), allOf(
|
||||
containsString("RabbitMessageBus does not support producer properties: "),
|
||||
containsString(getClassUnderTestName() + " does not support producer properties: "),
|
||||
containsString("partitionSelectorExpression"),
|
||||
containsString("partitionKeyExtractorClass"),
|
||||
containsString("partitionKeyExpression"),
|
||||
@@ -246,12 +254,12 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
assertThat(e.getMessage(), containsString("for dummy."));
|
||||
}
|
||||
try {
|
||||
bus.bindProducer("queue:dummy", new DirectChannel(), properties);
|
||||
binder.bindProducer("queue:dummy", new DirectChannel(), properties);
|
||||
fail("Expected exception");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), allOf(
|
||||
containsString("RabbitMessageBus does not support producer properties: "),
|
||||
containsString(getClassUnderTestName() + " does not support producer properties: "),
|
||||
containsString("partitionSelectorExpression"),
|
||||
containsString("partitionKeyExtractorClass"),
|
||||
containsString("partitionKeyExpression"),
|
||||
@@ -259,13 +267,13 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
assertThat(e.getMessage(), containsString("for queue:dummy."));
|
||||
}
|
||||
|
||||
bus.unbindProducers("props.0");
|
||||
binder.unbindProducers("props.0");
|
||||
assertEquals(0, bindings.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestReplyRequestorProperties() throws Exception {
|
||||
MessageBus bus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
Properties properties = new Properties();
|
||||
properties.put("prefix", "foo.");
|
||||
properties.put("deliveryMode", "NON_PERSISTENT");
|
||||
@@ -285,9 +293,9 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
properties.put("requeue", "false");
|
||||
properties.put("txSize", "10");
|
||||
|
||||
bus.bindRequestor("props.0", new DirectChannel(), new DirectChannel(), properties);
|
||||
binder.bindRequestor("props.0", new DirectChannel(), new DirectChannel(), properties);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(bus, "messageBus.bindings", List.class);
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(binder, "binder.bindings", List.class);
|
||||
|
||||
assertEquals(2, bindings.size());
|
||||
AbstractEndpoint endpoint = bindings.get(0).getEndpoint(); // producer
|
||||
@@ -308,15 +316,15 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
properties.put("partitionKeyExtractorClass", "foo");
|
||||
properties.put("partitionSelectorExpression", "0");
|
||||
properties.put("partitionSelectorClass", "foo");
|
||||
properties.put(BusProperties.NEXT_MODULE_COUNT, "1");
|
||||
properties.put(BinderProperties.NEXT_MODULE_COUNT, "1");
|
||||
properties.put("partitionIndex", "0");
|
||||
try {
|
||||
bus.bindRequestor("dummy", null, null, properties);
|
||||
binder.bindRequestor("dummy", null, null, properties);
|
||||
fail("Expected exception");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), allOf(
|
||||
containsString("RabbitMessageBus does not support producer properties: "),
|
||||
containsString(getClassUnderTestName() + " does not support producer properties: "),
|
||||
containsString("partitionSelectorExpression"),
|
||||
containsString("partitionKeyExtractorClass"),
|
||||
containsString("partitionKeyExpression"),
|
||||
@@ -324,14 +332,14 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
assertThat(e.getMessage(), allOf(containsString("partitionIndex"), containsString("for dummy.")));
|
||||
}
|
||||
|
||||
bus.unbindConsumers("props.0");
|
||||
bus.unbindProducers("props.0");
|
||||
binder.unbindConsumers("props.0");
|
||||
binder.unbindProducers("props.0");
|
||||
assertEquals(0, bindings.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestReplyReplierProperties() throws Exception {
|
||||
MessageBus bus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
Properties properties = new Properties();
|
||||
properties.put("prefix", "foo.");
|
||||
properties.put("deliveryMode", "NON_PERSISTENT");
|
||||
@@ -351,15 +359,16 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
properties.put("requeue", "false");
|
||||
properties.put("txSize", "10");
|
||||
|
||||
bus.bindReplier("props.0", new DirectChannel(), new DirectChannel(), properties);
|
||||
binder.bindReplier("props.0", new DirectChannel(), new DirectChannel(), properties);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(bus, "messageBus.bindings", List.class);
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(binder, "binder.bindings", List.class);
|
||||
|
||||
assertEquals(2, bindings.size());
|
||||
AbstractEndpoint endpoint = bindings.get(1).getEndpoint(); // producer
|
||||
assertEquals(
|
||||
"headers['amqp_replyTo']",
|
||||
TestUtils.getPropertyValue(endpoint, "handler.delegate.routingKeyExpression", SpelExpression.class).getExpressionString());
|
||||
TestUtils.getPropertyValue(endpoint, "handler.delegate.routingKeyExpression",
|
||||
SpelExpression.class).getExpressionString());
|
||||
MessageDeliveryMode mode = TestUtils.getPropertyValue(endpoint, "handler.delegate.defaultDeliveryMode",
|
||||
MessageDeliveryMode.class);
|
||||
assertEquals(MessageDeliveryMode.NON_PERSISTENT, mode);
|
||||
@@ -376,15 +385,15 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
properties.put("partitionKeyExtractorClass", "foo");
|
||||
properties.put("partitionSelectorExpression", "0");
|
||||
properties.put("partitionSelectorClass", "foo");
|
||||
properties.put(BusProperties.NEXT_MODULE_COUNT, "1");
|
||||
properties.put(BinderProperties.NEXT_MODULE_COUNT, "1");
|
||||
properties.put("partitionIndex", "0");
|
||||
try {
|
||||
bus.bindReplier("dummy", null, null, properties);
|
||||
binder.bindReplier("dummy", null, null, properties);
|
||||
fail("Expected exception");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), allOf(
|
||||
containsString("RabbitMessageBus does not support consumer properties: "),
|
||||
containsString(getClassUnderTestName() + " does not support consumer properties: "),
|
||||
containsString("partitionSelectorExpression"),
|
||||
containsString("partitionKeyExtractorClass"),
|
||||
containsString("partitionKeyExpression"),
|
||||
@@ -392,8 +401,8 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
assertThat(e.getMessage(), allOf(containsString("partitionIndex"), containsString("for dummy.")));
|
||||
}
|
||||
|
||||
bus.unbindConsumers("props.0");
|
||||
bus.unbindProducers("props.0");
|
||||
binder.unbindConsumers("props.0");
|
||||
binder.unbindProducers("props.0");
|
||||
assertEquals(0, bindings.size());
|
||||
}
|
||||
|
||||
@@ -401,9 +410,10 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
public void testDurablePubSubWithAutoBindDLQ() throws Exception {
|
||||
RabbitAdmin admin = new RabbitAdmin(this.rabbitAvailableRule.getResource());
|
||||
|
||||
MessageBus bus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
|
||||
Properties properties = new Properties();
|
||||
properties.put("prefix", "xdbustest.");
|
||||
properties.put("prefix", TEST_PREFIX);
|
||||
properties.put("autoBindDLQ", "true");
|
||||
properties.put("durableSubscription", "true");
|
||||
properties.put("maxAttempts", "1"); // disable retry
|
||||
@@ -418,14 +428,14 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
}
|
||||
|
||||
});
|
||||
bus.bindPubSubConsumer("teststream.tap:stream:durabletest.0", moduleInputChannel, properties);
|
||||
binder.bindPubSubConsumer("teststream.tap:stream:durabletest.0", moduleInputChannel, properties);
|
||||
|
||||
RabbitTemplate template = new RabbitTemplate(this.rabbitAvailableRule.getResource());
|
||||
template.convertAndSend("xdbustest.topic.tap:stream:durabletest.0", "", "foo");
|
||||
template.convertAndSend(TEST_PREFIX + "topic.tap:stream:durabletest.0", "", "foo");
|
||||
|
||||
int n = 0;
|
||||
while (n++ < 100) {
|
||||
Object deadLetter = template.receiveAndConvert("xdbustest.teststream.tap:stream:durabletest.0.dlq");
|
||||
Object deadLetter = template.receiveAndConvert(TEST_PREFIX + "teststream.tap:stream:durabletest.0.dlq");
|
||||
if (deadLetter != null) {
|
||||
assertEquals("foo", deadLetter);
|
||||
break;
|
||||
@@ -434,21 +444,21 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
}
|
||||
assertTrue(n < 100);
|
||||
|
||||
bus.unbindConsumer("teststream.tap:stream:durabletest.0", moduleInputChannel);
|
||||
assertNotNull(admin.getQueueProperties("xdbustest.teststream.tap:stream:durabletest.0.dlq"));
|
||||
admin.deleteQueue("xdbustest.teststream.tap:stream:durabletest.0.dlq");
|
||||
admin.deleteQueue("xdbustest.teststream.tap:stream:durabletest.0");
|
||||
admin.deleteExchange("xdbustest.topic.tap:stream:durabletest.0");
|
||||
admin.deleteExchange("xdbustest.DLX");
|
||||
binder.unbindConsumer("teststream.tap:stream:durabletest.0", moduleInputChannel);
|
||||
assertNotNull(admin.getQueueProperties(TEST_PREFIX + "teststream.tap:stream:durabletest.0.dlq"));
|
||||
admin.deleteQueue(TEST_PREFIX + "teststream.tap:stream:durabletest.0.dlq");
|
||||
admin.deleteQueue(TEST_PREFIX + "teststream.tap:stream:durabletest.0");
|
||||
admin.deleteExchange(TEST_PREFIX + "topic.tap:stream:durabletest.0");
|
||||
admin.deleteExchange(TEST_PREFIX + "DLX");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonDurablePubSubWithAutoBindDLQ() throws Exception {
|
||||
RabbitAdmin admin = new RabbitAdmin(this.rabbitAvailableRule.getResource());
|
||||
|
||||
MessageBus bus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
Properties properties = new Properties();
|
||||
properties.put("prefix", "xdbustest.");
|
||||
properties.put("prefix", TEST_PREFIX);
|
||||
properties.put("autoBindDLQ", "true");
|
||||
properties.put("durableSubscription", "false");
|
||||
properties.put("maxAttempts", "1"); // disable retry
|
||||
@@ -463,21 +473,21 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
}
|
||||
|
||||
});
|
||||
bus.bindPubSubConsumer("teststream.tap:stream:nondurabletest.0", moduleInputChannel, properties);
|
||||
binder.bindPubSubConsumer("teststream.tap:stream:nondurabletest.0", moduleInputChannel, properties);
|
||||
|
||||
bus.unbindConsumer("teststream.tap:stream:nondurabletest.0", moduleInputChannel);
|
||||
assertNull(admin.getQueueProperties("xdbustest.teststream.tap:stream:nondurabletest.0.dlq"));
|
||||
admin.deleteQueue("xdbustest.teststream.tap:stream:nondurabletest.0");
|
||||
admin.deleteExchange("xdbustest.topic.tap:stream:nondurabletest.0");
|
||||
binder.unbindConsumer("teststream.tap:stream:nondurabletest.0", moduleInputChannel);
|
||||
assertNull(admin.getQueueProperties(TEST_PREFIX + "teststream.tap:stream:nondurabletest.0.dlq"));
|
||||
admin.deleteQueue(TEST_PREFIX + "teststream.tap:stream:nondurabletest.0");
|
||||
admin.deleteExchange(TEST_PREFIX + "topic.tap:stream:nondurabletest.0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutoBindDLQ() throws Exception {
|
||||
RabbitAdmin admin = new RabbitAdmin(this.rabbitAvailableRule.getResource());
|
||||
|
||||
MessageBus bus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
Properties properties = new Properties();
|
||||
properties.put("prefix", "xdbustest.");
|
||||
properties.put("prefix", TEST_PREFIX);
|
||||
properties.put("autoBindDLQ", "true");
|
||||
properties.put("maxAttempts", "1"); // disable retry
|
||||
properties.put("requeue", "false");
|
||||
@@ -491,14 +501,14 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
}
|
||||
|
||||
});
|
||||
bus.bindConsumer("dlqtest", moduleInputChannel, properties);
|
||||
binder.bindConsumer("dlqtest", moduleInputChannel, properties);
|
||||
|
||||
RabbitTemplate template = new RabbitTemplate(this.rabbitAvailableRule.getResource());
|
||||
template.convertAndSend("", "xdbustest.dlqtest", "foo");
|
||||
template.convertAndSend("", TEST_PREFIX + "dlqtest", "foo");
|
||||
|
||||
int n = 0;
|
||||
while (n++ < 100) {
|
||||
Object deadLetter = template.receiveAndConvert("xdbustest.dlqtest.dlq");
|
||||
Object deadLetter = template.receiveAndConvert(TEST_PREFIX + "dlqtest.dlq");
|
||||
if (deadLetter != null) {
|
||||
assertEquals("foo", deadLetter);
|
||||
break;
|
||||
@@ -507,10 +517,10 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
}
|
||||
assertTrue(n < 100);
|
||||
|
||||
bus.unbindConsumer("dlqtest", moduleInputChannel);
|
||||
admin.deleteQueue("xdbustest.dlqtest.dlq");
|
||||
admin.deleteQueue("xdbustest.dlqtest");
|
||||
admin.deleteExchange("xdbustest.DLX");
|
||||
binder.unbindConsumer("dlqtest", moduleInputChannel);
|
||||
admin.deleteQueue(TEST_PREFIX + "dlqtest.dlq");
|
||||
admin.deleteQueue(TEST_PREFIX + "dlqtest");
|
||||
admin.deleteExchange(TEST_PREFIX + "DLX");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -518,13 +528,13 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
// pre-declare the queue with dead-lettering, users can also use a policy
|
||||
RabbitAdmin admin = new RabbitAdmin(this.rabbitAvailableRule.getResource());
|
||||
Map<String, Object> args = new HashMap<String, Object>();
|
||||
args.put("x-dead-letter-exchange", "xdbustest.DLX");
|
||||
Queue queue = new Queue("xdbustest.dlqpubtest", true, false, false, args);
|
||||
args.put("x-dead-letter-exchange", TEST_PREFIX + "DLX");
|
||||
Queue queue = new Queue(TEST_PREFIX + "dlqpubtest", true, false, false, args);
|
||||
admin.declareQueue(queue);
|
||||
|
||||
MessageBus bus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
Properties properties = new Properties();
|
||||
properties.put("prefix", "xdbustest.");
|
||||
properties.put("prefix", TEST_PREFIX);
|
||||
properties.put("autoBindDLQ", "true");
|
||||
properties.put("republishToDLQ", "true");
|
||||
properties.put("maxAttempts", "1"); // disable retry
|
||||
@@ -539,14 +549,14 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
}
|
||||
|
||||
});
|
||||
bus.bindConsumer("dlqpubtest", moduleInputChannel, properties);
|
||||
binder.bindConsumer("dlqpubtest", moduleInputChannel, properties);
|
||||
|
||||
RabbitTemplate template = new RabbitTemplate(this.rabbitAvailableRule.getResource());
|
||||
template.convertAndSend("", "xdbustest.dlqpubtest", "foo");
|
||||
template.convertAndSend("", TEST_PREFIX + "dlqpubtest", "foo");
|
||||
|
||||
int n = 0;
|
||||
while (n++ < 100) {
|
||||
org.springframework.amqp.core.Message deadLetter = template.receive("xdbustest.dlqpubtest.dlq");
|
||||
org.springframework.amqp.core.Message deadLetter = template.receive(TEST_PREFIX + "dlqpubtest.dlq");
|
||||
if (deadLetter != null) {
|
||||
assertEquals("foo", new String(deadLetter.getBody()));
|
||||
assertNotNull(deadLetter.getMessageProperties().getHeaders().get("x-exception-stacktrace"));
|
||||
@@ -556,17 +566,17 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
}
|
||||
assertTrue(n < 100);
|
||||
|
||||
bus.unbindConsumer("dlqpubtest", moduleInputChannel);
|
||||
admin.deleteQueue("xdbustest.dlqpubtest.dlq");
|
||||
admin.deleteQueue("xdbustest.dlqpubtest");
|
||||
admin.deleteExchange("xdbustest.DLX");
|
||||
binder.unbindConsumer("dlqpubtest", moduleInputChannel);
|
||||
admin.deleteQueue(TEST_PREFIX + "dlqpubtest.dlq");
|
||||
admin.deleteQueue(TEST_PREFIX + "dlqpubtest");
|
||||
admin.deleteExchange(TEST_PREFIX + "DLX");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testBatchingAndCompression() throws Exception {
|
||||
RabbitTemplate template = new RabbitTemplate(this.rabbitAvailableRule.getResource());
|
||||
MessageBus bus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
Properties properties = new Properties();
|
||||
properties.put("deliveryMode", "NON_PERSISTENT");
|
||||
properties.put("batchingEnabled", "true");
|
||||
@@ -577,17 +587,17 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
|
||||
DirectChannel output = new DirectChannel();
|
||||
output.setBeanName("batchingProducer");
|
||||
bus.bindProducer("batching.0", output, properties);
|
||||
binder.bindProducer("batching.0", output, properties);
|
||||
|
||||
while (template.receive("xdbus.batching.0") != null) {
|
||||
while (template.receive(BINDER_PREFIX + "batching.0") != null) {
|
||||
}
|
||||
|
||||
Log logger = spy(TestUtils.getPropertyValue(bus, "messageBus.compressingPostProcessor.logger", Log.class));
|
||||
new DirectFieldAccessor(TestUtils.getPropertyValue(bus, "messageBus.compressingPostProcessor"))
|
||||
Log logger = spy(TestUtils.getPropertyValue(binder, "binder.compressingPostProcessor.logger", Log.class));
|
||||
new DirectFieldAccessor(TestUtils.getPropertyValue(binder, "binder.compressingPostProcessor"))
|
||||
.setPropertyValue("logger", logger);
|
||||
when(logger.isTraceEnabled()).thenReturn(true);
|
||||
|
||||
assertEquals(Deflater.BEST_SPEED, TestUtils.getPropertyValue(bus, "messageBus.compressingPostProcessor.level"));
|
||||
assertEquals(Deflater.BEST_SPEED, TestUtils.getPropertyValue(binder, "binder.compressingPostProcessor.level"));
|
||||
|
||||
output.send(new GenericMessage<>("foo".getBytes()));
|
||||
output.send(new GenericMessage<>("bar".getBytes()));
|
||||
@@ -602,7 +612,7 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
|
||||
QueueChannel input = new QueueChannel();
|
||||
input.setBeanName("batchingConsumer");
|
||||
bus.bindConsumer("batching.0", input, null);
|
||||
binder.bindConsumer("batching.0", input, null);
|
||||
|
||||
output.send(new GenericMessage<>("foo".getBytes()));
|
||||
output.send(new GenericMessage<>("bar".getBytes()));
|
||||
@@ -615,8 +625,8 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
assertEquals("bar", new String(in.getPayload()));
|
||||
assertNull(in.getHeaders().get(AmqpHeaders.DELIVERY_MODE));
|
||||
|
||||
bus.unbindProducers("batching.0");
|
||||
bus.unbindConsumers("batching.0");
|
||||
binder.unbindProducers("batching.0");
|
||||
binder.unbindConsumers("batching.0");
|
||||
}
|
||||
|
||||
private SimpleMessageListenerContainer verifyContainer(AbstractEndpoint endpoint) {
|
||||
@@ -679,12 +689,19 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
|
||||
@Override
|
||||
protected String getEndpointRouting(AbstractEndpoint endpoint) {
|
||||
return TestUtils.getPropertyValue(endpoint, "handler.delegate.routingKeyExpression", SpelExpression.class).getExpressionString();
|
||||
return TestUtils.getPropertyValue(endpoint, "handler.delegate.routingKeyExpression",
|
||||
SpelExpression.class).getExpressionString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPubSubEndpointRouting(AbstractEndpoint endpoint) {
|
||||
return TestUtils.getPropertyValue(endpoint, "handler.delegate.exchangeNameExpression", SpelExpression.class).getExpressionString();
|
||||
return TestUtils.getPropertyValue(endpoint, "handler.delegate.exchangeNameExpression",
|
||||
SpelExpression.class).getExpressionString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getClassUnderTestName() {
|
||||
return CLASS_UNDER_TEST_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -697,12 +714,12 @@ public class RabbitMessageBusTests extends PartitionCapableBusTests {
|
||||
public Object receive(boolean expectNull) throws Exception {
|
||||
if (expectNull) {
|
||||
Thread.sleep(50);
|
||||
return template.receiveAndConvert("xdbus." + queue);
|
||||
return template.receiveAndConvert(BINDER_PREFIX + queue);
|
||||
}
|
||||
Object bar = null;
|
||||
int n = 0;
|
||||
while (n++ < 100 && bar == null) {
|
||||
bar = template.receiveAndConvert("xdbus." + queue);
|
||||
bar = template.receiveAndConvert(BINDER_PREFIX + queue);
|
||||
Thread.sleep(100);
|
||||
}
|
||||
assertTrue("Message did not arrive in RabbitMQ", n < 100);
|
||||
@@ -14,41 +14,43 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.rabbit;
|
||||
package org.springframework.cloud.stream.binder.rabbit;
|
||||
|
||||
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
|
||||
import org.springframework.amqp.rabbit.core.RabbitAdmin;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.xd.dirt.integration.bus.AbstractTestMessageBus;
|
||||
import org.springframework.cloud.stream.binder.AbstractTestBinder;
|
||||
import org.springframework.xd.dirt.integration.bus.serializer.MultiTypeCodec;
|
||||
|
||||
|
||||
/**
|
||||
* Test support class for {@link org.springframework.xd.dirt.integration.rabbit.RabbitMessageBus}.
|
||||
* Test support class for {@link RabbitMessageChannelBinder}.
|
||||
*
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public class RabbitTestMessageBus extends AbstractTestMessageBus<RabbitMessageBus> {
|
||||
public class RabbitTestBinder extends AbstractTestBinder<RabbitMessageChannelBinder> {
|
||||
|
||||
public static final String BINDER_PREFIX = "binder.rabbit.";
|
||||
|
||||
private final RabbitAdmin rabbitAdmin;
|
||||
|
||||
public RabbitTestMessageBus(ConnectionFactory connectionFactory) {
|
||||
public RabbitTestBinder(ConnectionFactory connectionFactory) {
|
||||
this.rabbitAdmin = new RabbitAdmin(connectionFactory);
|
||||
}
|
||||
|
||||
public RabbitTestMessageBus(ConnectionFactory connectionFactory, MultiTypeCodec<Object> codec) {
|
||||
RabbitMessageBus messageBus = new RabbitMessageBus(connectionFactory, codec);
|
||||
public RabbitTestBinder(ConnectionFactory connectionFactory, MultiTypeCodec<Object> codec) {
|
||||
RabbitMessageChannelBinder binder = new RabbitMessageChannelBinder(connectionFactory, codec);
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
|
||||
scheduler.setPoolSize(1);
|
||||
scheduler.afterPropertiesSet();
|
||||
context.getBeanFactory().registerSingleton(IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME, scheduler);
|
||||
context.refresh();
|
||||
messageBus.setApplicationContext(context);
|
||||
this.setMessageBus(messageBus);
|
||||
binder.setApplicationContext(context);
|
||||
this.setBinder(binder);
|
||||
this.rabbitAdmin = new RabbitAdmin(connectionFactory);
|
||||
}
|
||||
|
||||
@@ -56,10 +58,10 @@ public class RabbitTestMessageBus extends AbstractTestMessageBus<RabbitMessageBu
|
||||
public void cleanup() {
|
||||
if (!queues.isEmpty()) {
|
||||
for (String queue : queues) {
|
||||
rabbitAdmin.deleteQueue("xdbus." + queue);
|
||||
rabbitAdmin.deleteQueue(BINDER_PREFIX + queue);
|
||||
// delete any partitioned queues
|
||||
for (int i = 0; i < 10; i++) {
|
||||
rabbitAdmin.deleteQueue("xdbus." + queue + "-" + i);
|
||||
rabbitAdmin.deleteQueue(BINDER_PREFIX + queue + "-" + i);
|
||||
}
|
||||
rabbitAdmin.deleteQueue("foo." + queue);
|
||||
// delete any partitioned queues
|
||||
@@ -70,7 +72,7 @@ public class RabbitTestMessageBus extends AbstractTestMessageBus<RabbitMessageBu
|
||||
}
|
||||
if (!topics.isEmpty()) {
|
||||
for (String exchange : topics) {
|
||||
rabbitAdmin.deleteExchange("xdbus." + exchange);
|
||||
rabbitAdmin.deleteExchange(BINDER_PREFIX + exchange);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,11 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.rabbit;
|
||||
package org.springframework.cloud.stream.binder.rabbit;
|
||||
|
||||
|
||||
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
|
||||
import org.springframework.xd.test.AbstractExternalResourceTestSupport;
|
||||
import org.springframework.cloud.stream.binder.AbstractExternalResourceTestSupport;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
import java.net.Socket;
|
||||
@@ -5,4 +5,4 @@ log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %40.40c:%4L - %m%n
|
||||
|
||||
log4j.category.org.springframework.xd.dirt.integration.rabbit=DEBUG
|
||||
log4j.category.org.springframework.cloud.binder.rabbit=DEBUG
|
||||
@@ -3,14 +3,14 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-cloud-stream-binding-redis</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-redis</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>spring-cloud-stream-binding-redis</name>
|
||||
<description>Redis binding implementation</description>
|
||||
<name>spring-cloud-stream-binder-redis</name>
|
||||
<description>Redis binder implementation</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-bindings-parent</artifactId>
|
||||
<artifactId>spring-cloud-stream-binders-parent</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-spi</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-test</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-test</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.redis;
|
||||
package org.springframework.cloud.stream.binder.redis;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -23,6 +23,7 @@ import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.cloud.stream.binder.BinderHeaders;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
@@ -46,24 +47,22 @@ import org.springframework.retry.RetryContext;
|
||||
import org.springframework.retry.support.RetryTemplate;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.xd.dirt.integration.bus.AbstractBusPropertiesAccessor;
|
||||
import org.springframework.xd.dirt.integration.bus.Binding;
|
||||
import org.springframework.xd.dirt.integration.bus.BusProperties;
|
||||
import org.springframework.xd.dirt.integration.bus.EmbeddedHeadersMessageConverter;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageBus;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageBusSupport;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageValues;
|
||||
import org.springframework.xd.dirt.integration.bus.XdHeaders;
|
||||
import org.springframework.cloud.stream.binder.AbstractBinderPropertiesAccessor;
|
||||
import org.springframework.cloud.stream.binder.Binding;
|
||||
import org.springframework.cloud.stream.binder.BinderProperties;
|
||||
import org.springframework.cloud.stream.binder.EmbeddedHeadersMessageConverter;
|
||||
import org.springframework.cloud.stream.binder.MessageChannelBinderSupport;
|
||||
import org.springframework.cloud.stream.binder.MessageValues;
|
||||
import org.springframework.xd.dirt.integration.bus.serializer.MultiTypeCodec;
|
||||
|
||||
/**
|
||||
* A {@link MessageBus} implementation backed by Redis.
|
||||
* A {@link org.springframework.cloud.stream.binder.Binder} implementation backed by Redis.
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
* @author David Turanski
|
||||
* @author Jennifer Hickey
|
||||
*/
|
||||
public class RedisMessageBus extends MessageBusSupport implements DisposableBean {
|
||||
public class RedisMessageChannelBinder extends MessageChannelBinderSupport implements DisposableBean {
|
||||
|
||||
private static final String ERROR_HEADER = "errorKey";
|
||||
|
||||
@@ -85,7 +84,7 @@ public class RedisMessageBus extends MessageBusSupport implements DisposableBean
|
||||
private static final Set<Object> SUPPORTED_NAMED_CONSUMER_PROPERTIES = new SetBuilder()
|
||||
.addAll(CONSUMER_STANDARD_PROPERTIES)
|
||||
.addAll(CONSUMER_RETRY_PROPERTIES)
|
||||
.add(BusProperties.CONCURRENCY)
|
||||
.add(BinderProperties.CONCURRENCY)
|
||||
.build();
|
||||
|
||||
/**
|
||||
@@ -93,7 +92,7 @@ public class RedisMessageBus extends MessageBusSupport implements DisposableBean
|
||||
*/
|
||||
private static final Set<Object> SUPPORTED_CONSUMER_PROPERTIES = new SetBuilder()
|
||||
.addAll(SUPPORTED_NAMED_CONSUMER_PROPERTIES)
|
||||
.add(BusProperties.PARTITION_INDEX)
|
||||
.add(BinderProperties.PARTITION_INDEX)
|
||||
.build();
|
||||
|
||||
/**
|
||||
@@ -103,7 +102,7 @@ public class RedisMessageBus extends MessageBusSupport implements DisposableBean
|
||||
// request
|
||||
.addAll(CONSUMER_STANDARD_PROPERTIES)
|
||||
.addAll(CONSUMER_RETRY_PROPERTIES)
|
||||
.add(BusProperties.CONCURRENCY)
|
||||
.add(BinderProperties.CONCURRENCY)
|
||||
.build();
|
||||
|
||||
/**
|
||||
@@ -122,7 +121,7 @@ public class RedisMessageBus extends MessageBusSupport implements DisposableBean
|
||||
private static final Set<Object> SUPPORTED_PRODUCER_PROPERTIES = new SetBuilder()
|
||||
.addAll(PRODUCER_PARTITIONING_PROPERTIES)
|
||||
.addAll(PRODUCER_STANDARD_PROPERTIES)
|
||||
.add(BusProperties.DIRECT_BINDING_ALLOWED)
|
||||
.add(BinderProperties.DIRECT_BINDING_ALLOWED)
|
||||
.build();
|
||||
|
||||
/**
|
||||
@@ -131,7 +130,7 @@ public class RedisMessageBus extends MessageBusSupport implements DisposableBean
|
||||
private static final Set<Object> SUPPORTED_REQUESTING_PRODUCER_PROPERTIES = new SetBuilder()
|
||||
// reply
|
||||
.addAll(CONSUMER_RETRY_PROPERTIES)
|
||||
.add(BusProperties.CONCURRENCY)
|
||||
.add(BinderProperties.CONCURRENCY)
|
||||
.build();
|
||||
|
||||
private final RedisConnectionFactory connectionFactory;
|
||||
@@ -141,11 +140,11 @@ public class RedisMessageBus extends MessageBusSupport implements DisposableBean
|
||||
|
||||
private final RedisQueueOutboundChannelAdapter errorAdapter;
|
||||
|
||||
public RedisMessageBus(RedisConnectionFactory connectionFactory, MultiTypeCodec<Object> codec) {
|
||||
public RedisMessageChannelBinder(RedisConnectionFactory connectionFactory, MultiTypeCodec<Object> codec) {
|
||||
this(connectionFactory, codec, new String[0]);
|
||||
}
|
||||
|
||||
public RedisMessageBus(RedisConnectionFactory connectionFactory, MultiTypeCodec<Object> codec,
|
||||
public RedisMessageChannelBinder(RedisConnectionFactory connectionFactory, MultiTypeCodec<Object> codec,
|
||||
String... headersToMap) {
|
||||
Assert.notNull(connectionFactory, "connectionFactory must not be null");
|
||||
Assert.notNull(codec, "codec must not be null");
|
||||
@@ -155,14 +154,14 @@ public class RedisMessageBus extends MessageBusSupport implements DisposableBean
|
||||
parser.parseExpression("headers['" + ERROR_HEADER + "']"), connectionFactory);
|
||||
if (headersToMap != null && headersToMap.length > 0) {
|
||||
String[] combinedHeadersToMap =
|
||||
Arrays.copyOfRange(XdHeaders.STANDARD_HEADERS, 0, XdHeaders.STANDARD_HEADERS.length
|
||||
Arrays.copyOfRange(BinderHeaders.STANDARD_HEADERS, 0, BinderHeaders.STANDARD_HEADERS.length
|
||||
+ headersToMap.length);
|
||||
System.arraycopy(headersToMap, 0, combinedHeadersToMap, XdHeaders.STANDARD_HEADERS.length,
|
||||
System.arraycopy(headersToMap, 0, combinedHeadersToMap, BinderHeaders.STANDARD_HEADERS.length,
|
||||
headersToMap.length);
|
||||
this.headersToMap = combinedHeadersToMap;
|
||||
}
|
||||
else {
|
||||
this.headersToMap = XdHeaders.STANDARD_HEADERS;
|
||||
this.headersToMap = BinderHeaders.STANDARD_HEADERS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,7 +387,7 @@ public class RedisMessageBus extends MessageBusSupport implements DisposableBean
|
||||
this.doRegisterConsumer(name, name, requests, adapter, accessor);
|
||||
|
||||
RedisQueueOutboundChannelAdapter replyQueue = new RedisQueueOutboundChannelAdapter(
|
||||
RedisMessageBus.parser.parseExpression("headers['" + XdHeaders.REPLY_TO + "']"),
|
||||
RedisMessageChannelBinder.parser.parseExpression("headers['" + BinderHeaders.REPLY_TO + "']"),
|
||||
this.connectionFactory);
|
||||
replyQueue.setBeanFactory(this.getBeanFactory());
|
||||
replyQueue.setIntegrationEvaluationContext(this.evaluationContext);
|
||||
@@ -414,7 +413,7 @@ public class RedisMessageBus extends MessageBusSupport implements DisposableBean
|
||||
this.delegate = delegate;
|
||||
this.replyTo = replyTo;
|
||||
this.partitioningMetadata = new PartitioningMetadata(properties, properties.getNextModuleCount());
|
||||
this.setBeanFactory(RedisMessageBus.this.getBeanFactory());
|
||||
this.setBeanFactory(RedisMessageChannelBinder.this.getBeanFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -422,7 +421,7 @@ public class RedisMessageBus extends MessageBusSupport implements DisposableBean
|
||||
MessageValues transformed = serializePayloadIfNecessary(message);
|
||||
|
||||
if (replyTo != null) {
|
||||
transformed.put(XdHeaders.REPLY_TO, this.replyTo);
|
||||
transformed.put(BinderHeaders.REPLY_TO, this.replyTo);
|
||||
}
|
||||
if (this.partitioningMetadata.isPartitionedModule()) {
|
||||
|
||||
@@ -430,7 +429,7 @@ public class RedisMessageBus extends MessageBusSupport implements DisposableBean
|
||||
}
|
||||
|
||||
byte[] messageToSend = embeddedHeadersMessageConverter.embedHeaders(transformed,
|
||||
RedisMessageBus.this.headersToMap);
|
||||
RedisMessageChannelBinder.this.headersToMap);
|
||||
delegate.handleMessage(MessageBuilder.withPayload(messageToSend).copyHeaders(transformed).build());
|
||||
}
|
||||
|
||||
@@ -440,7 +439,7 @@ public class RedisMessageBus extends MessageBusSupport implements DisposableBean
|
||||
|
||||
public ReceivingHandler() {
|
||||
super();
|
||||
this.setBeanFactory(RedisMessageBus.this.getBeanFactory());
|
||||
this.setBeanFactory(RedisMessageChannelBinder.this.getBeanFactory());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -464,7 +463,7 @@ public class RedisMessageBus extends MessageBusSupport implements DisposableBean
|
||||
}
|
||||
}
|
||||
|
||||
private static class RedisPropertiesAccessor extends AbstractBusPropertiesAccessor {
|
||||
private static class RedisPropertiesAccessor extends AbstractBinderPropertiesAccessor {
|
||||
|
||||
public RedisPropertiesAccessor(Properties properties) {
|
||||
super(properties);
|
||||
@@ -484,12 +483,12 @@ public class RedisMessageBus extends MessageBusSupport implements DisposableBean
|
||||
for (int i = 0; i < concurrency; i++) {
|
||||
RedisQueueMessageDrivenEndpoint adapter = new RedisQueueMessageDrivenEndpoint(queueName,
|
||||
connectionFactory);
|
||||
adapter.setBeanFactory(RedisMessageBus.this.getBeanFactory());
|
||||
adapter.setBeanFactory(RedisMessageChannelBinder.this.getBeanFactory());
|
||||
adapter.setSerializer(null);
|
||||
adapter.setBeanName("inbound." + queueName + "." + i);
|
||||
this.consumers.add(adapter);
|
||||
}
|
||||
this.setBeanFactory(RedisMessageBus.this.getBeanFactory());
|
||||
this.setBeanFactory(RedisMessageChannelBinder.this.getBeanFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* This package contains an implementation of the {@link org.springframework.cloud.stream.binder.Binder} for Redis.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.stream.binder.redis;
|
||||
@@ -5,7 +5,7 @@
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<bean id="messageBus" class="org.springframework.xd.dirt.integration.redis.RedisMessageBus">
|
||||
<bean id="messageBus" class="org.springframework.cloud.stream.binder.redis.RedisMessageChannelBinder">
|
||||
<constructor-arg ref="redisConnectionFactory" />
|
||||
<constructor-arg ref="codec"/>
|
||||
<constructor-arg value="${xd.messagebus.redis.headers:}" />
|
||||
@@ -11,7 +11,7 @@
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.redis;
|
||||
package org.springframework.cloud.stream.binder.redis;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus.redis;
|
||||
package org.springframework.cloud.stream.binder.redis;
|
||||
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
@@ -37,6 +37,7 @@ import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.cloud.stream.binder.PartitionCapableBinderTests;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
@@ -47,19 +48,18 @@ import org.springframework.integration.redis.inbound.RedisQueueMessageDrivenEndp
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.retry.support.RetryTemplate;
|
||||
import org.springframework.xd.dirt.integration.bus.Binding;
|
||||
import org.springframework.xd.dirt.integration.bus.BusProperties;
|
||||
import org.springframework.xd.dirt.integration.bus.EmbeddedHeadersMessageConverter;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageBus;
|
||||
import org.springframework.xd.dirt.integration.bus.PartitionCapableBusTests;
|
||||
import org.springframework.xd.dirt.integration.bus.Spy;
|
||||
import org.springframework.xd.dirt.integration.redis.RedisMessageBus;
|
||||
import org.springframework.xd.dirt.integration.redis.RedisTestSupport;
|
||||
import org.springframework.cloud.stream.binder.Binding;
|
||||
import org.springframework.cloud.stream.binder.BinderProperties;
|
||||
import org.springframework.cloud.stream.binder.EmbeddedHeadersMessageConverter;
|
||||
import org.springframework.cloud.stream.binder.Binder;
|
||||
import org.springframework.cloud.stream.binder.Spy;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
public class RedisBinderTests extends PartitionCapableBinderTests {
|
||||
|
||||
private final String CLASS_UNDER_TEST_NAME = RedisMessageChannelBinder.class.getSimpleName();
|
||||
|
||||
@Rule
|
||||
public RedisTestSupport redisAvailableRule = new RedisTestSupport();
|
||||
@@ -70,11 +70,11 @@ public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
new EmbeddedHeadersMessageConverter();
|
||||
|
||||
@Override
|
||||
protected MessageBus getMessageBus() {
|
||||
if (testMessageBus == null) {
|
||||
testMessageBus = new RedisTestMessageBus(redisAvailableRule.getResource(), getCodec());
|
||||
protected Binder getBinder() {
|
||||
if (testBinder == null) {
|
||||
testBinder = new RedisTestBinder(redisAvailableRule.getResource(), getCodec());
|
||||
}
|
||||
return testMessageBus;
|
||||
return testBinder;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -97,17 +97,17 @@ public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
|
||||
@Test
|
||||
public void testConsumerProperties() throws Exception {
|
||||
MessageBus bus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
Properties properties = new Properties();
|
||||
properties.put("maxAttempts", "1"); // disable retry
|
||||
bus.bindConsumer("props.0", new DirectChannel(), properties);
|
||||
binder.bindConsumer("props.0", new DirectChannel(), properties);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(bus, "messageBus.bindings", List.class);
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(binder, "binder.bindings", List.class);
|
||||
assertEquals(1, bindings.size());
|
||||
AbstractEndpoint endpoint = bindings.get(0).getEndpoint();
|
||||
assertThat(endpoint, instanceOf(RedisQueueMessageDrivenEndpoint.class));
|
||||
assertSame(DirectChannel.class, TestUtils.getPropertyValue(endpoint, "outputChannel").getClass());
|
||||
bus.unbindConsumers("props.0");
|
||||
binder.unbindConsumers("props.0");
|
||||
assertEquals(0, bindings.size());
|
||||
|
||||
properties.put("backOffInitialInterval", "2000");
|
||||
@@ -117,47 +117,47 @@ public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
properties.put("maxAttempts", "23");
|
||||
properties.put("partitionIndex", 0);
|
||||
|
||||
bus.bindConsumer("props.0", new DirectChannel(), properties);
|
||||
binder.bindConsumer("props.0", new DirectChannel(), properties);
|
||||
assertEquals(1, bindings.size());
|
||||
endpoint = bindings.get(0).getEndpoint();
|
||||
verifyConsumer(endpoint);
|
||||
|
||||
try {
|
||||
bus.bindPubSubConsumer("dummy", null, properties);
|
||||
binder.bindPubSubConsumer("dummy", null, properties);
|
||||
fail("Expected exception");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), allOf(
|
||||
containsString("RedisMessageBus does not support consumer properties: "),
|
||||
containsString(getClassUnderTestName() + " does not support consumer properties: "),
|
||||
containsString("partitionIndex"),
|
||||
containsString("concurrency"),
|
||||
containsString(" for dummy.")));
|
||||
}
|
||||
try {
|
||||
bus.bindConsumer("queue:dummy", null, properties);
|
||||
binder.bindConsumer("queue:dummy", null, properties);
|
||||
fail("Expected exception");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertEquals("RedisMessageBus does not support consumer property: partitionIndex for queue:dummy.",
|
||||
assertEquals(getClassUnderTestName() + " does not support consumer property: partitionIndex for queue:dummy.",
|
||||
e.getMessage());
|
||||
}
|
||||
|
||||
bus.unbindConsumers("props.0");
|
||||
binder.unbindConsumers("props.0");
|
||||
assertEquals(0, bindings.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProducerProperties() throws Exception {
|
||||
MessageBus bus = getMessageBus();
|
||||
bus.bindProducer("props.0", new DirectChannel(), null);
|
||||
Binder binder = getBinder();
|
||||
binder.bindProducer("props.0", new DirectChannel(), null);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(bus, "messageBus.bindings", List.class);
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(binder, "binder.bindings", List.class);
|
||||
assertEquals(1, bindings.size());
|
||||
AbstractEndpoint endpoint = bindings.get(0).getEndpoint();
|
||||
assertEquals(
|
||||
"queue.props.0",
|
||||
TestUtils.getPropertyValue(endpoint, "handler.delegate.queueNameExpression", Expression.class).getExpressionString());
|
||||
bus.unbindProducers("props.0");
|
||||
binder.unbindProducers("props.0");
|
||||
assertEquals(0, bindings.size());
|
||||
|
||||
Properties properties = new Properties();
|
||||
@@ -165,9 +165,9 @@ public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
properties.put("partitionKeyExtractorClass", "foo");
|
||||
properties.put("partitionSelectorExpression", "0");
|
||||
properties.put("partitionSelectorClass", "foo");
|
||||
properties.put(BusProperties.NEXT_MODULE_COUNT, "1");
|
||||
properties.put(BinderProperties.NEXT_MODULE_COUNT, "1");
|
||||
|
||||
bus.bindProducer("props.0", new DirectChannel(), properties);
|
||||
binder.bindProducer("props.0", new DirectChannel(), properties);
|
||||
assertEquals(1, bindings.size());
|
||||
endpoint = bindings.get(0).getEndpoint();
|
||||
assertEquals(
|
||||
@@ -175,12 +175,12 @@ public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
TestUtils.getPropertyValue(endpoint, "handler.delegate.queueNameExpression", Expression.class).getExpressionString());
|
||||
|
||||
try {
|
||||
bus.bindPubSubProducer("dummy", null, properties);
|
||||
binder.bindPubSubProducer("dummy", null, properties);
|
||||
fail("Expected exception");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), allOf(
|
||||
containsString("RedisMessageBus does not support producer properties: "),
|
||||
containsString(getClassUnderTestName() + " does not support producer properties: "),
|
||||
containsString("partitionSelectorExpression"),
|
||||
containsString("partitionKeyExtractorClass"),
|
||||
containsString("partitionKeyExpression"),
|
||||
@@ -188,12 +188,12 @@ public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
assertThat(e.getMessage(), containsString("for dummy."));
|
||||
}
|
||||
try {
|
||||
bus.bindProducer("queue:dummy", new DirectChannel(), properties);
|
||||
binder.bindProducer("queue:dummy", new DirectChannel(), properties);
|
||||
fail("Expected exception");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), allOf(
|
||||
containsString("RedisMessageBus does not support producer properties: "),
|
||||
containsString(getClassUnderTestName() + " does not support producer properties: "),
|
||||
containsString("partitionSelectorExpression"),
|
||||
containsString("partitionKeyExtractorClass"),
|
||||
containsString("partitionKeyExpression"),
|
||||
@@ -201,13 +201,13 @@ public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
assertThat(e.getMessage(), containsString("for queue:dummy."));
|
||||
}
|
||||
|
||||
bus.unbindProducers("props.0");
|
||||
binder.unbindProducers("props.0");
|
||||
assertEquals(0, bindings.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestReplyRequestorProperties() throws Exception {
|
||||
MessageBus bus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
Properties properties = new Properties();
|
||||
|
||||
properties.put("backOffInitialInterval", "2000");
|
||||
@@ -216,9 +216,9 @@ public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
properties.put("concurrency", "2");
|
||||
properties.put("maxAttempts", "23");
|
||||
|
||||
bus.bindRequestor("props.0", new DirectChannel(), new DirectChannel(), properties);
|
||||
binder.bindRequestor("props.0", new DirectChannel(), new DirectChannel(), properties);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(bus, "messageBus.bindings", List.class);
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(binder, "binder.bindings", List.class);
|
||||
|
||||
assertEquals(2, bindings.size());
|
||||
AbstractEndpoint endpoint = bindings.get(0).getEndpoint(); // producer
|
||||
@@ -235,12 +235,12 @@ public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
properties.put("partitionSelectorClass", "foo");
|
||||
properties.put("partitionIndex", "0");
|
||||
try {
|
||||
bus.bindRequestor("dummy", new DirectChannel(), new DirectChannel(), properties);
|
||||
binder.bindRequestor("dummy", new DirectChannel(), new DirectChannel(), properties);
|
||||
fail("Expected exception");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), allOf(
|
||||
containsString("RedisMessageBus does not support producer properties: "),
|
||||
containsString(getClassUnderTestName() + " does not support producer properties: "),
|
||||
containsString("partitionSelectorExpression"),
|
||||
containsString("partitionKeyExtractorClass"),
|
||||
containsString("partitionKeyExpression"),
|
||||
@@ -248,14 +248,14 @@ public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
assertThat(e.getMessage(), allOf(containsString("partitionIndex"), containsString("for dummy.")));
|
||||
}
|
||||
|
||||
bus.unbindConsumers("props.0");
|
||||
bus.unbindProducers("props.0");
|
||||
binder.unbindConsumers("props.0");
|
||||
binder.unbindProducers("props.0");
|
||||
assertEquals(0, bindings.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestReplyReplierProperties() throws Exception {
|
||||
MessageBus bus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
Properties properties = new Properties();
|
||||
|
||||
properties.put("backOffInitialInterval", "2000");
|
||||
@@ -264,9 +264,9 @@ public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
properties.put("concurrency", "2");
|
||||
properties.put("maxAttempts", "23");
|
||||
|
||||
bus.bindReplier("props.0", new DirectChannel(), new DirectChannel(), properties);
|
||||
binder.bindReplier("props.0", new DirectChannel(), new DirectChannel(), properties);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(bus, "messageBus.bindings", List.class);
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(binder, "binder.bindings", List.class);
|
||||
|
||||
assertEquals(2, bindings.size());
|
||||
AbstractEndpoint endpoint = bindings.get(1).getEndpoint(); // producer
|
||||
@@ -281,15 +281,15 @@ public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
properties.put("partitionKeyExtractorClass", "foo");
|
||||
properties.put("partitionSelectorExpression", "0");
|
||||
properties.put("partitionSelectorClass", "foo");
|
||||
properties.put(BusProperties.NEXT_MODULE_COUNT, "1");
|
||||
properties.put(BinderProperties.NEXT_MODULE_COUNT, "1");
|
||||
properties.put("partitionIndex", "0");
|
||||
try {
|
||||
bus.bindReplier("dummy", new DirectChannel(), new DirectChannel(), properties);
|
||||
binder.bindReplier("dummy", new DirectChannel(), new DirectChannel(), properties);
|
||||
fail("Expected exception");
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), allOf(
|
||||
containsString("RedisMessageBus does not support consumer properties: "),
|
||||
containsString(getClassUnderTestName() + " does not support consumer properties: "),
|
||||
containsString("partitionSelectorExpression"),
|
||||
containsString("partitionKeyExtractorClass"),
|
||||
containsString("partitionKeyExpression"),
|
||||
@@ -297,8 +297,8 @@ public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
assertThat(e.getMessage(), allOf(containsString("partitionIndex"), containsString("for dummy.")));
|
||||
}
|
||||
|
||||
bus.unbindConsumers("props.0");
|
||||
bus.unbindProducers("props.0");
|
||||
binder.unbindConsumers("props.0");
|
||||
binder.unbindProducers("props.0");
|
||||
assertEquals(0, bindings.size());
|
||||
}
|
||||
|
||||
@@ -309,10 +309,10 @@ public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
TestUtils.getPropertyValue(endpoint, "consumers", List.class).get(0),
|
||||
"outputChannel", DirectChannel.class);
|
||||
assertThat(
|
||||
channel.getClass().getName(), containsString("RedisMessageBus$")); // retry wrapper
|
||||
channel.getClass().getName(), containsString(getClassUnderTestName() + "$")); // retry wrapper
|
||||
assertThat(
|
||||
TestUtils.getPropertyValue(TestUtils.getPropertyValue(endpoint, "consumers", List.class).get(1),
|
||||
"outputChannel").getClass().getName(), containsString("RedisMessageBus$")); // retry wrapper
|
||||
"outputChannel").getClass().getName(), containsString(getClassUnderTestName() + "$")); // retry wrapper
|
||||
RetryTemplate retry = TestUtils.getPropertyValue(channel, "val$retryTemplate", RetryTemplate.class);
|
||||
assertEquals(23, TestUtils.getPropertyValue(retry, "retryPolicy.maxAttempts"));
|
||||
assertEquals(2000L, TestUtils.getPropertyValue(retry, "backOffPolicy.initialInterval"));
|
||||
@@ -322,14 +322,14 @@ public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
|
||||
@Test
|
||||
public void testRetryFail() {
|
||||
MessageBus bus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
DirectChannel channel = new DirectChannel();
|
||||
bus.bindProducer("retry.0", channel, null);
|
||||
binder.bindProducer("retry.0", channel, null);
|
||||
Properties props = new Properties();
|
||||
props.put("maxAttempts", 2);
|
||||
props.put("backOffInitialInterval", 100);
|
||||
props.put("backOffMultiplier", "1.0");
|
||||
bus.bindConsumer("retry.0", new DirectChannel(), props); // no subscriber
|
||||
binder.bindConsumer("retry.0", new DirectChannel(), props); // no subscriber
|
||||
channel.send(new GenericMessage<String>("foo"));
|
||||
RedisTemplate<String, Object> template = createTemplate();
|
||||
Object rightPop = template.boundListOps("ERRORS:retry.0").rightPop(5, TimeUnit.SECONDS);
|
||||
@@ -339,8 +339,8 @@ public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
|
||||
@Test
|
||||
public void testMoreHeaders() {
|
||||
RedisMessageBus bus = new RedisMessageBus(mock(RedisConnectionFactory.class), getCodec(), "foo", "bar");
|
||||
Collection<String> headers = Arrays.asList(TestUtils.getPropertyValue(bus, "headersToMap", String[].class));
|
||||
RedisMessageChannelBinder binder = new RedisMessageChannelBinder(mock(RedisConnectionFactory.class), getCodec(), "foo", "bar");
|
||||
Collection<String> headers = Arrays.asList(TestUtils.getPropertyValue(binder, "headersToMap", String[].class));
|
||||
assertEquals(10, headers.size());
|
||||
assertTrue(headers.contains("foo"));
|
||||
assertTrue(headers.contains("bar"));
|
||||
@@ -369,6 +369,11 @@ public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
return TestUtils.getPropertyValue(endpoint, "handler.delegate.topicExpression", Expression.class).getExpressionString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getClassUnderTestName() {
|
||||
return CLASS_UNDER_TEST_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spy spyOn(final String queue) {
|
||||
final RedisTemplate<String, Object> template = createTemplate();
|
||||
@@ -388,7 +393,7 @@ public class RedisMessageBusTests extends PartitionCapableBusTests {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void busBindUnbindLatency() throws InterruptedException {
|
||||
protected void binderBindUnbindLatency() throws InterruptedException {
|
||||
Thread.sleep(3000); // needed for Redis see INT-3442
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.redis;
|
||||
package org.springframework.cloud.stream.binder.redis;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.cloud.stream.binder.BinderTestUtils;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.listener.ChannelTopic;
|
||||
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
|
||||
@@ -36,7 +37,6 @@ import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
import org.springframework.integration.redis.outbound.RedisPublishingMessageHandler;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.xd.dirt.integration.bus.BusTestUtils;
|
||||
|
||||
/**
|
||||
* Temporary copy of SI RedisPublishingMessageHandlerTests that adds tests that publish messages with data types other
|
||||
@@ -70,7 +70,7 @@ public class RedisPublishingMessageHandlerTests {
|
||||
public void testWithDefaultSerializer() throws Exception {
|
||||
setupListener(new StringRedisSerializer());
|
||||
final RedisPublishingMessageHandler handler = new RedisPublishingMessageHandler(connectionFactory);
|
||||
handler.setBeanFactory(BusTestUtils.MOCK_BF);
|
||||
handler.setBeanFactory(BinderTestUtils.MOCK_BF);
|
||||
handler.setTopic(TOPIC);
|
||||
handler.afterPropertiesSet();
|
||||
for (int i = 0; i < NUM_MESSAGES; i++) {
|
||||
@@ -85,7 +85,7 @@ public class RedisPublishingMessageHandlerTests {
|
||||
public void testWithNoSerializer() throws Exception {
|
||||
setupListener(null);
|
||||
final RedisPublishingMessageHandler handler = new RedisPublishingMessageHandler(connectionFactory);
|
||||
handler.setBeanFactory(BusTestUtils.MOCK_BF);
|
||||
handler.setBeanFactory(BinderTestUtils.MOCK_BF);
|
||||
handler.setTopic(TOPIC);
|
||||
handler.afterPropertiesSet();
|
||||
for (int i = 0; i < NUM_MESSAGES; i++) {
|
||||
@@ -101,7 +101,7 @@ public class RedisPublishingMessageHandlerTests {
|
||||
GenericToStringSerializer<Long> serializer = new GenericToStringSerializer<Long>(Long.class);
|
||||
setupListener(serializer);
|
||||
final RedisPublishingMessageHandler handler = new RedisPublishingMessageHandler(connectionFactory);
|
||||
handler.setBeanFactory(BusTestUtils.MOCK_BF);
|
||||
handler.setBeanFactory(BinderTestUtils.MOCK_BF);
|
||||
handler.setTopic(TOPIC);
|
||||
handler.setSerializer(serializer);
|
||||
handler.afterPropertiesSet();
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.redis;
|
||||
package org.springframework.cloud.stream.binder.redis;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@@ -30,6 +30,7 @@ import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.cloud.stream.binder.BinderTestUtils;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.GenericToStringSerializer;
|
||||
@@ -43,7 +44,6 @@ import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.xd.dirt.integration.bus.BusTestUtils;
|
||||
|
||||
/**
|
||||
* Integration test of {@link RedisQueueInboundChannelAdapter}
|
||||
@@ -70,13 +70,13 @@ public class RedisQueueInboundChannelAdapterTests {
|
||||
messages.clear();
|
||||
this.connectionFactory = redisAvailableRule.getResource();
|
||||
DirectChannel outputChannel = new DirectChannel();
|
||||
outputChannel.setBeanFactory(BusTestUtils.MOCK_BF);
|
||||
outputChannel.setBeanFactory(BinderTestUtils.MOCK_BF);
|
||||
outputChannel.subscribe(new TestMessageHandler());
|
||||
|
||||
this.currentQueueName = QUEUE_NAME + ":" + System.nanoTime();
|
||||
|
||||
adapter = new RedisQueueMessageDrivenEndpoint(currentQueueName, connectionFactory);
|
||||
adapter.setBeanFactory(BusTestUtils.MOCK_BF);
|
||||
adapter.setBeanFactory(BinderTestUtils.MOCK_BF);
|
||||
adapter.setOutputChannel(outputChannel);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.redis;
|
||||
package org.springframework.cloud.stream.binder.redis;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.cloud.stream.binder.BinderTestUtils;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
@@ -37,7 +38,6 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
import org.springframework.integration.redis.outbound.RedisQueueOutboundChannelAdapter;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.xd.dirt.integration.bus.BusTestUtils;
|
||||
|
||||
/**
|
||||
* Integration test of {@link RedisQueueOutboundChannelAdapter}
|
||||
@@ -60,7 +60,7 @@ public class RedisQueueOutboundChannelAdapterTests {
|
||||
public void setUp() {
|
||||
this.connectionFactory = redisAvailableRule.getResource();
|
||||
adapter = new RedisQueueOutboundChannelAdapter(QUEUE_NAME, connectionFactory);
|
||||
adapter.setBeanFactory(BusTestUtils.MOCK_BF);
|
||||
adapter.setBeanFactory(BinderTestUtils.MOCK_BF);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus.redis;
|
||||
package org.springframework.cloud.stream.binder.redis;
|
||||
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
@@ -24,27 +24,26 @@ import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.support.DefaultMessageBuilderFactory;
|
||||
import org.springframework.integration.support.utils.IntegrationUtils;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.xd.dirt.integration.bus.AbstractTestMessageBus;
|
||||
import org.springframework.cloud.stream.binder.AbstractTestBinder;
|
||||
import org.springframework.xd.dirt.integration.bus.serializer.MultiTypeCodec;
|
||||
import org.springframework.xd.dirt.integration.redis.RedisMessageBus;
|
||||
|
||||
|
||||
/**
|
||||
* Test support class for {@link RedisMessageBus}.
|
||||
* Test support class for {@link RedisMessageChannelBinder}.
|
||||
*
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public class RedisTestMessageBus extends AbstractTestMessageBus<RedisMessageBus> {
|
||||
public class RedisTestBinder extends AbstractTestBinder<RedisMessageChannelBinder> {
|
||||
|
||||
private StringRedisTemplate template;
|
||||
|
||||
public RedisTestMessageBus(RedisConnectionFactory connectionFactory) {
|
||||
public RedisTestBinder(RedisConnectionFactory connectionFactory) {
|
||||
template = new StringRedisTemplate(connectionFactory);
|
||||
}
|
||||
|
||||
public RedisTestMessageBus(RedisConnectionFactory connectionFactory, MultiTypeCodec<Object> codec) {
|
||||
RedisMessageBus messageBus = new RedisMessageBus(connectionFactory, codec);
|
||||
public RedisTestBinder(RedisConnectionFactory connectionFactory, MultiTypeCodec<Object> codec) {
|
||||
RedisMessageChannelBinder binder = new RedisMessageChannelBinder(connectionFactory, codec);
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.getBeanFactory().registerSingleton(IntegrationUtils.INTEGRATION_MESSAGE_BUILDER_FACTORY_BEAN_NAME,
|
||||
new DefaultMessageBuilderFactory());
|
||||
@@ -57,8 +56,8 @@ public class RedisTestMessageBus extends AbstractTestMessageBus<RedisMessageBus>
|
||||
IntegrationContextUtils.INTEGRATION_HEADER_CHANNEL_REGISTRY_BEAN_NAME,
|
||||
channelRegistry);
|
||||
context.refresh();
|
||||
messageBus.setApplicationContext(context);
|
||||
setMessageBus(messageBus);
|
||||
binder.setApplicationContext(context);
|
||||
setBinder(binder);
|
||||
template = new StringRedisTemplate(connectionFactory);
|
||||
}
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.redis;
|
||||
package org.springframework.cloud.stream.binder.redis;
|
||||
|
||||
import org.junit.Rule;
|
||||
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||
import org.springframework.xd.test.AbstractExternalResourceTestSupport;
|
||||
import org.springframework.cloud.stream.binder.AbstractExternalResourceTestSupport;
|
||||
|
||||
/**
|
||||
* JUnit {@link Rule} that detects the fact that a Redis server is running on localhost.
|
||||
@@ -3,14 +3,14 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-cloud-stream-binding-spi</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-spi</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>spring-cloud-stream-binding-spi</name>
|
||||
<description>SPI for binding implementations</description>
|
||||
<name>spring-cloud-stream-binder-spi</name>
|
||||
<description>SPI for binder implementations</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-bindings-parent</artifactId>
|
||||
<artifactId>spring-cloud-stream-binders-parent</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
@@ -24,18 +24,18 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Base class for bus-specific property accessors; common properties
|
||||
* Base class for binder-specific property accessors; common properties
|
||||
* are defined here.
|
||||
*
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public abstract class AbstractBusPropertiesAccessor implements BusProperties {
|
||||
public abstract class AbstractBinderPropertiesAccessor implements BinderProperties {
|
||||
|
||||
private static final SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
|
||||
|
||||
private final Properties properties;
|
||||
|
||||
public AbstractBusPropertiesAccessor(Properties properties) {
|
||||
public AbstractBinderPropertiesAccessor(Properties properties) {
|
||||
if (properties == null) {
|
||||
this.properties = new Properties();
|
||||
}
|
||||
@@ -142,7 +142,7 @@ public abstract class AbstractBusPropertiesAccessor implements BusProperties {
|
||||
|
||||
/**
|
||||
* Return the 'concurrency' property or the default value.
|
||||
* The meaning of concurrency depends on the bus implementation.
|
||||
* The meaning of concurrency depends on the binder implementation.
|
||||
* @param defaultValue The default value.
|
||||
* @return The property or default value.
|
||||
*/
|
||||
@@ -152,7 +152,7 @@ public abstract class AbstractBusPropertiesAccessor implements BusProperties {
|
||||
|
||||
/**
|
||||
* Return the 'maxConcurrency' property or the default value.
|
||||
* The meaning of maxConcurrency depends on the bus implementation.
|
||||
* The meaning of maxConcurrency depends on the binder implementation.
|
||||
* @param defaultValue The default value.
|
||||
* @return The property or default value.
|
||||
*/
|
||||
@@ -165,7 +165,7 @@ public abstract class AbstractBusPropertiesAccessor implements BusProperties {
|
||||
/**
|
||||
* Return the 'maxAttempts' property or the default value.
|
||||
* This is used in the retry template's SimpleRetryPolicy
|
||||
* in buses that support retry.
|
||||
* in binders that support retry.
|
||||
* @param defaultValue The default value.
|
||||
* @return The property or default value.
|
||||
*/
|
||||
@@ -176,7 +176,7 @@ public abstract class AbstractBusPropertiesAccessor implements BusProperties {
|
||||
/**
|
||||
* Return the 'backOffInitialInterval' property or the default value.
|
||||
* This is used in the retry template's ExponentialBackOffPolicy
|
||||
* in buses that support retry.
|
||||
* in binders that support retry.
|
||||
* @param defaultValue The default value.
|
||||
* @return The property or default value.
|
||||
*/
|
||||
@@ -187,7 +187,7 @@ public abstract class AbstractBusPropertiesAccessor implements BusProperties {
|
||||
/**
|
||||
* Return the 'backOffMultiplier' property or the default value.
|
||||
* This is used in the retry template's ExponentialBackOffPolicy
|
||||
* in buses that support retry.
|
||||
* in binders that support retry.
|
||||
* @param defaultValue The default value.
|
||||
* @return The property or default value.
|
||||
*/
|
||||
@@ -198,7 +198,7 @@ public abstract class AbstractBusPropertiesAccessor implements BusProperties {
|
||||
/**
|
||||
* Return the 'backOffMaxInterval' property or the default value.
|
||||
* This is used in the retry template's ExponentialBackOffPolicy
|
||||
* in buses that support retry.
|
||||
* in binders that support retry.
|
||||
* @param defaultValue The default value.
|
||||
* @return The property or default value.
|
||||
*/
|
||||
@@ -291,7 +291,7 @@ public abstract class AbstractBusPropertiesAccessor implements BusProperties {
|
||||
// Direct Binding
|
||||
|
||||
/**
|
||||
* If true, the bus can attempt a direct binding.
|
||||
* If true, the binder can attempt a direct binding.
|
||||
*/
|
||||
public boolean isDirectBindingAllowed() {
|
||||
return getProperty(DIRECT_BINDING_ALLOWED, false);
|
||||
@@ -11,14 +11,14 @@
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
|
||||
/**
|
||||
* A strategy interface used to bind a {@link MessageChannel} to a logical name. The name is intended to identify a
|
||||
* A strategy interface used to bind a module interface to a logical name. The name is intended to identify a
|
||||
* logical consumer or producer of messages. This may be a queue, a channel adapter, another message channel, a Spring
|
||||
* bean, etc.
|
||||
*
|
||||
@@ -29,55 +29,55 @@ import org.springframework.messaging.MessageChannel;
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @since 1.0
|
||||
*/
|
||||
public interface MessageBus {
|
||||
public interface Binder<T> {
|
||||
|
||||
/**
|
||||
* Bind a message consumer on a p2p channel
|
||||
*
|
||||
* @param name the logical identity of the message source
|
||||
* @param moduleInputChannel the channel bound as a consumer
|
||||
* @param inboundBindTarget the module interface to be bound as a point to point consumer
|
||||
* @param properties arbitrary String key/value pairs that will be used in the binding
|
||||
*/
|
||||
void bindConsumer(String name, MessageChannel moduleInputChannel, Properties properties);
|
||||
void bindConsumer(String name, T inboundBindTarget, Properties properties);
|
||||
|
||||
|
||||
/**
|
||||
* Bind a message consumer on a pub/sub channel
|
||||
*
|
||||
* @param name the logical identity of the message source
|
||||
* @param inputChannel the channel bound as a pub/sub consumer
|
||||
* @param inboundBindTarget the module interface to be bound as a pub/sub consumer
|
||||
* @param properties arbitrary String key/value pairs that will be used in the binding
|
||||
*/
|
||||
void bindPubSubConsumer(final String name, MessageChannel inputChannel, Properties properties);
|
||||
void bindPubSubConsumer(final String name, T inboundBindTarget, Properties properties);
|
||||
|
||||
/**
|
||||
* Bind a message producer on a p2p channel.
|
||||
*
|
||||
* @param name the logical identity of the message target
|
||||
* @param moduleOutputChannel the channel bound as a producer
|
||||
* @param outboundBindTarget the module interface bound as a producer
|
||||
* @param properties arbitrary String key/value pairs that will be used in the binding
|
||||
*/
|
||||
void bindProducer(String name, MessageChannel moduleOutputChannel, Properties properties);
|
||||
void bindProducer(String name, T outboundBindTarget, Properties properties);
|
||||
|
||||
|
||||
/**
|
||||
* Bind a message producer on a pub/sub channel.
|
||||
*
|
||||
* @param name the logical identity of the message target
|
||||
* @param outputChannel the channel bound as a producer
|
||||
* @param outboundBindTarget the module interface bound as a producer
|
||||
* @param properties arbitrary String key/value pairs that will be used in the binding
|
||||
*/
|
||||
void bindPubSubProducer(final String name, MessageChannel outputChannel, Properties properties);
|
||||
void bindPubSubProducer(final String name, T outboundBindTarget, Properties properties);
|
||||
|
||||
/**
|
||||
* Unbind an inbound inter-module channel and stop any active components that use the channel.
|
||||
* Unbind inbound module components and stop any active components that use the channel.
|
||||
*
|
||||
* @param name the channel name
|
||||
*/
|
||||
void unbindConsumers(String name);
|
||||
|
||||
/**
|
||||
* Unbind an outbound inter-module channel and stop any active components that use the channel.
|
||||
* Unbind an outbound module components and stop any active components that use the channel.
|
||||
*
|
||||
* @param name the channel name
|
||||
*/
|
||||
@@ -87,59 +87,59 @@ public interface MessageBus {
|
||||
* Unbind a specific p2p or pub/sub message consumer
|
||||
*
|
||||
* @param name The logical identify of a message source
|
||||
* @param channel The channel bound as a consumer
|
||||
* @param inboundBindTarget The module interface bound as a consumer
|
||||
*/
|
||||
void unbindConsumer(String name, MessageChannel channel);
|
||||
void unbindConsumer(String name, T inboundBindTarget);
|
||||
|
||||
/**
|
||||
* Unbind a specific p2p or pub/sub message producer
|
||||
*
|
||||
* @param name the logical identity of the message target
|
||||
* @param channel the channel bound as a producer
|
||||
* @param outboundBindTarget the channel bound as a producer
|
||||
*/
|
||||
void unbindProducer(String name, MessageChannel channel);
|
||||
void unbindProducer(String name, T outboundBindTarget);
|
||||
|
||||
/**
|
||||
* Bind a producer that expects async replies. To unbind, invoke unbindProducer() and unbindConsumer().
|
||||
*
|
||||
* @param name The name of the requestor.
|
||||
* @param requests The request channel - sends requests.
|
||||
* @param replies The reply channel - receives replies.
|
||||
* @param requests The interface used to send requests.
|
||||
* @param replies The interface used to receive replies.
|
||||
* @param properties arbitrary String key/value pairs that will be used in the binding.
|
||||
*/
|
||||
void bindRequestor(String name, MessageChannel requests, MessageChannel replies, Properties properties);
|
||||
void bindRequestor(String name, T requests, T replies, Properties properties);
|
||||
|
||||
/**
|
||||
* Bind a consumer that handles requests from a requestor and asynchronously sends replies. To unbind, invoke
|
||||
* unbindProducer() and unbindConsumer().
|
||||
*
|
||||
* @param name The name of the requestor for which this replier will handle requests.
|
||||
* @param requests The request channel - receives requests.
|
||||
* @param replies The reply channel - sends replies.
|
||||
* @param requests The interface used to send requests.
|
||||
* @param replies The interface used to receive replies.
|
||||
* @param properties arbitrary String key/value pairs that will be used in the binding.
|
||||
*/
|
||||
void bindReplier(String name, MessageChannel requests, MessageChannel replies, Properties properties);
|
||||
void bindReplier(String name, T requests, T replies, Properties properties);
|
||||
|
||||
/**
|
||||
* Create a channel and bind a producer dynamically, creating the infrastructure
|
||||
* required by the bus technology.
|
||||
* Create a object and bind a producer dynamically, creating the infrastructure
|
||||
* required by the binder technology.
|
||||
* @param name The name of the "queue:" channel.
|
||||
* @param properties arbitrary String key/value pairs that will be used in the binding.
|
||||
* @return The channel.
|
||||
* @return The bound object.
|
||||
*/
|
||||
MessageChannel bindDynamicProducer(String name, Properties properties);
|
||||
T bindDynamicProducer(String name, Properties properties);
|
||||
|
||||
/**
|
||||
* Create a channel and bind a producer dynamically, creating the infrastructure
|
||||
* required by the bus technology to broadcast messages to consumers.
|
||||
* Create an object and bind a producer dynamically, creating the infrastructure
|
||||
* required by the binder technology to broadcast messages to consumers.
|
||||
* @param name The name of the "topic:" channel.
|
||||
* @param properties arbitrary String key/value pairs that will be used in the binding.
|
||||
* @return The channel.
|
||||
* @return The bound Object.
|
||||
*/
|
||||
MessageChannel bindDynamicPubSubProducer(String name, Properties properties);
|
||||
T bindDynamicPubSubProducer(String name, Properties properties);
|
||||
|
||||
/**
|
||||
* Return true if the bus supports the capability.
|
||||
* Return true if the binder supports the capability.
|
||||
* @param capability the capability.
|
||||
* @return true if the capability is supported.
|
||||
*/
|
||||
@@ -148,7 +148,7 @@ public interface MessageBus {
|
||||
public enum Capability {
|
||||
|
||||
/**
|
||||
* When a bus supports durable subscriptions to a pub/sub channel, the stream
|
||||
* When a binder supports durable subscriptions to a pub/sub channel, the stream
|
||||
* name will be included in the consumer name.
|
||||
*/
|
||||
DURABLE_PUBSUB
|
||||
@@ -13,19 +13,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* Interface for implementations that perform cleanup for message buses.
|
||||
* Interface for implementations that perform cleanup for binders.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 1.2
|
||||
*/
|
||||
public interface BusCleaner {
|
||||
public interface BinderCleaner {
|
||||
|
||||
/**
|
||||
* Clean up all resources for the supplied stream/job.
|
||||
@@ -14,19 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
|
||||
/**
|
||||
* Exception thrown to indicate a message bus error (most
|
||||
* Exception thrown to indicate a binder error (most
|
||||
* likely a configuration error).
|
||||
*
|
||||
* @author Gary Russell
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MessageBusException extends RuntimeException {
|
||||
public class BinderException extends RuntimeException {
|
||||
|
||||
public MessageBusException(String message, Throwable cause) {
|
||||
public BinderException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import org.springframework.integration.IntegrationMessageHeaderAccessor;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
@@ -24,17 +24,18 @@ import org.springframework.messaging.MessageHeaders;
|
||||
* Spring Integration message headers for XD.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @author David Turanski
|
||||
*/
|
||||
public final class XdHeaders {
|
||||
public final class BinderHeaders {
|
||||
|
||||
public static final String XD_REPLY_CHANNEL = "xdReplyChannel";
|
||||
public static final String BINDER_REPLY_CHANNEL = "binderReplyChannel";
|
||||
|
||||
public static final String XD_HISTORY = "xdHistory";
|
||||
public static final String BINDER_HISTORY = "binderHistory";
|
||||
|
||||
/*
|
||||
* no xd prefix for backwards compatibility
|
||||
*/
|
||||
public static final String XD_ORIGINAL_CONTENT_TYPE = "originalContentType";
|
||||
public static final String BINDER_ORIGINAL_CONTENT_TYPE = "originalContentType";
|
||||
|
||||
/*
|
||||
* no xd prefix for backwards compatibility
|
||||
@@ -42,21 +43,21 @@ public final class XdHeaders {
|
||||
public static final String REPLY_TO = "replyTo";
|
||||
|
||||
/**
|
||||
* The headers that will be propagated, by default, by message bus implementations
|
||||
* The headers that will be propagated, by default, by binder implementations
|
||||
* that have no inherent header support (by embedding the headers in the payload).
|
||||
*/
|
||||
public static final String[] STANDARD_HEADERS = new String[] {
|
||||
IntegrationMessageHeaderAccessor.CORRELATION_ID,
|
||||
IntegrationMessageHeaderAccessor.SEQUENCE_SIZE,
|
||||
IntegrationMessageHeaderAccessor.SEQUENCE_NUMBER,
|
||||
XD_REPLY_CHANNEL,
|
||||
BINDER_REPLY_CHANNEL,
|
||||
MessageHeaders.CONTENT_TYPE,
|
||||
XD_ORIGINAL_CONTENT_TYPE,
|
||||
BINDER_ORIGINAL_CONTENT_TYPE,
|
||||
REPLY_TO,
|
||||
XD_HISTORY
|
||||
BINDER_HISTORY
|
||||
};
|
||||
|
||||
private XdHeaders() {
|
||||
private BinderHeaders() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,15 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
|
||||
/**
|
||||
* Common bus properties.
|
||||
* Common binder properties.
|
||||
*
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public interface BusProperties {
|
||||
public interface BinderProperties {
|
||||
|
||||
/**
|
||||
* The retry back off initial interval.
|
||||
@@ -92,7 +92,7 @@ public interface BusProperties {
|
||||
public static final String PARTITION_SELECTOR_EXPRESSION = "partitionSelectorExpression";
|
||||
|
||||
/**
|
||||
* If true, the bus will attempt to create a direct binding between the producer and consumer.
|
||||
* If true, the binder will attempt to create a direct binding between the producer and consumer.
|
||||
*/
|
||||
public static final String DIRECT_BINDING_ALLOWED = "directBindingAllowed";
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -22,14 +22,14 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Message Bus utilities.
|
||||
* Binder utilities.
|
||||
*
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public class BusUtils {
|
||||
public class BinderUtils {
|
||||
|
||||
/**
|
||||
* The delimiter between a group and index when constructing a bus consumer/producer.
|
||||
* The delimiter between a group and index when constructing a binder consumer/producer.
|
||||
*/
|
||||
public static final String GROUP_INDEX_DELIMITER = ".";
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.integration.endpoint.AbstractEndpoint;
|
||||
@@ -22,10 +22,10 @@ import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Represents a binding between a module's channel and an adapter endpoint that connects to the MessageBus. The binding
|
||||
* could be for a consumer or a producer. A consumer binding represents a connection from an adapter on the bus to a
|
||||
* Represents a binding between a module's channel and an adapter endpoint that connects to the Binder. The binding
|
||||
* could be for a consumer or a producer. A consumer binding represents a connection from an adapter on the binder to a
|
||||
* module's input channel. A producer binding represents a connection from a module's output channel to an adapter on
|
||||
* the bus.
|
||||
* the binder.
|
||||
*
|
||||
* @author Jennifer Hickey
|
||||
* @author Mark Fisher
|
||||
@@ -47,10 +47,10 @@ public class Binding implements Lifecycle {
|
||||
|
||||
private final String type;
|
||||
|
||||
private final AbstractBusPropertiesAccessor properties;
|
||||
private final AbstractBinderPropertiesAccessor properties;
|
||||
|
||||
private Binding(String name, MessageChannel channel, AbstractEndpoint endpoint, String type,
|
||||
AbstractBusPropertiesAccessor properties) {
|
||||
AbstractBinderPropertiesAccessor properties) {
|
||||
Assert.notNull(channel, "channel must not be null");
|
||||
Assert.notNull(endpoint, "endpoint must not be null");
|
||||
this.name = name;
|
||||
@@ -60,18 +60,18 @@ public class Binding implements Lifecycle {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public static Binding forConsumer(String name, AbstractEndpoint adapterFromBus, MessageChannel moduleInputChannel,
|
||||
AbstractBusPropertiesAccessor properties) {
|
||||
return new Binding(name, moduleInputChannel, adapterFromBus, CONSUMER, properties);
|
||||
public static Binding forConsumer(String name, AbstractEndpoint adapterFromBinder, MessageChannel moduleInputChannel,
|
||||
AbstractBinderPropertiesAccessor properties) {
|
||||
return new Binding(name, moduleInputChannel, adapterFromBinder, CONSUMER, properties);
|
||||
}
|
||||
|
||||
public static Binding forProducer(String name, MessageChannel moduleOutputChannel, AbstractEndpoint adapterToBus,
|
||||
AbstractBusPropertiesAccessor properties) {
|
||||
return new Binding(name, moduleOutputChannel, adapterToBus, PRODUCER, properties);
|
||||
public static Binding forProducer(String name, MessageChannel moduleOutputChannel, AbstractEndpoint adapterToBinder,
|
||||
AbstractBinderPropertiesAccessor properties) {
|
||||
return new Binding(name, moduleOutputChannel, adapterToBinder, PRODUCER, properties);
|
||||
}
|
||||
|
||||
public static Binding forDirectProducer(String name, MessageChannel moduleOutputChannel,
|
||||
AbstractEndpoint adapter, AbstractBusPropertiesAccessor properties) {
|
||||
AbstractEndpoint adapter, AbstractBinderPropertiesAccessor properties) {
|
||||
return new Binding(name, moduleOutputChannel, adapter, DIRECT, properties);
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ public class Binding implements Lifecycle {
|
||||
return type;
|
||||
}
|
||||
|
||||
public AbstractBusPropertiesAccessor getPropertiesAccessor() {
|
||||
public AbstractBinderPropertiesAccessor getPropertiesAccessor() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -11,13 +11,7 @@
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
|
||||
import static org.springframework.util.MimeTypeUtils.ALL;
|
||||
import static org.springframework.util.MimeTypeUtils.APPLICATION_OCTET_STREAM;
|
||||
import static org.springframework.util.MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE;
|
||||
import static org.springframework.util.MimeTypeUtils.TEXT_PLAIN;
|
||||
import static org.springframework.util.MimeTypeUtils.TEXT_PLAIN_VALUE;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -48,6 +42,7 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.core.serializer.support.SerializationFailedException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
@@ -69,15 +64,20 @@ import org.springframework.util.IdGenerator;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.xd.dirt.integration.bus.serializer.MultiTypeCodec;
|
||||
import org.springframework.xd.dirt.integration.bus.serializer.SerializationException;
|
||||
|
||||
import static org.springframework.util.MimeTypeUtils.ALL;
|
||||
import static org.springframework.util.MimeTypeUtils.APPLICATION_OCTET_STREAM;
|
||||
import static org.springframework.util.MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE;
|
||||
import static org.springframework.util.MimeTypeUtils.TEXT_PLAIN;
|
||||
import static org.springframework.util.MimeTypeUtils.TEXT_PLAIN_VALUE;
|
||||
|
||||
/**
|
||||
* @author David Turanski
|
||||
* @author Gary Russell
|
||||
* @author Ilayaperumal Gopinathan
|
||||
*/
|
||||
public abstract class MessageBusSupport
|
||||
implements MessageBus, ApplicationContextAware, InitializingBean {
|
||||
public abstract class MessageChannelBinderSupport
|
||||
implements Binder<MessageChannel>, ApplicationContextAware, InitializingBean {
|
||||
|
||||
protected static final String P2P_NAMED_CHANNEL_TYPE_PREFIX = "queue:";
|
||||
|
||||
@@ -116,45 +116,45 @@ public abstract class MessageBusSupport
|
||||
private static final int DEFAULT_BATCH_TIMEOUT = 0;
|
||||
|
||||
/**
|
||||
* The set of properties every bus implementation must support (or at least tolerate).
|
||||
* The set of properties every binder implementation must support (or at least tolerate).
|
||||
*/
|
||||
|
||||
protected static final Set<Object> CONSUMER_STANDARD_PROPERTIES = new SetBuilder()
|
||||
.add(BusProperties.COUNT)
|
||||
.add(BusProperties.SEQUENCE)
|
||||
.add(BinderProperties.COUNT)
|
||||
.add(BinderProperties.SEQUENCE)
|
||||
.build();
|
||||
|
||||
protected static final Set<Object> PRODUCER_STANDARD_PROPERTIES = new HashSet<Object>(Arrays.asList(
|
||||
BusProperties.NEXT_MODULE_COUNT,
|
||||
BusProperties.NEXT_MODULE_CONCURRENCY
|
||||
));
|
||||
BinderProperties.NEXT_MODULE_COUNT,
|
||||
BinderProperties.NEXT_MODULE_CONCURRENCY
|
||||
));
|
||||
|
||||
|
||||
protected static final Set<Object> CONSUMER_RETRY_PROPERTIES = new HashSet<Object>(Arrays.asList(new String[] {
|
||||
BusProperties.BACK_OFF_INITIAL_INTERVAL,
|
||||
BusProperties.BACK_OFF_MAX_INTERVAL,
|
||||
BusProperties.BACK_OFF_MULTIPLIER,
|
||||
BusProperties.MAX_ATTEMPTS
|
||||
BinderProperties.BACK_OFF_INITIAL_INTERVAL,
|
||||
BinderProperties.BACK_OFF_MAX_INTERVAL,
|
||||
BinderProperties.BACK_OFF_MULTIPLIER,
|
||||
BinderProperties.MAX_ATTEMPTS
|
||||
}));
|
||||
|
||||
protected static final Set<Object> PRODUCER_PARTITIONING_PROPERTIES = new HashSet<Object>(
|
||||
Arrays.asList(new String[] {
|
||||
BusProperties.PARTITION_KEY_EXPRESSION,
|
||||
BusProperties.PARTITION_KEY_EXTRACTOR_CLASS,
|
||||
BusProperties.PARTITION_SELECTOR_CLASS,
|
||||
BusProperties.PARTITION_SELECTOR_EXPRESSION,
|
||||
BinderProperties.PARTITION_KEY_EXPRESSION,
|
||||
BinderProperties.PARTITION_KEY_EXTRACTOR_CLASS,
|
||||
BinderProperties.PARTITION_SELECTOR_CLASS,
|
||||
BinderProperties.PARTITION_SELECTOR_EXPRESSION,
|
||||
}));
|
||||
|
||||
protected static final Set<Object> PRODUCER_BATCHING_BASIC_PROPERTIES = new HashSet<Object>(
|
||||
Arrays.asList(new String[] {
|
||||
BusProperties.BATCHING_ENABLED,
|
||||
BusProperties.BATCH_SIZE,
|
||||
BusProperties.BATCH_TIMEOUT,
|
||||
BinderProperties.BATCHING_ENABLED,
|
||||
BinderProperties.BATCH_SIZE,
|
||||
BinderProperties.BATCH_TIMEOUT,
|
||||
}));
|
||||
|
||||
protected static final Set<Object> PRODUCER_BATCHING_ADVANCED_PROPERTIES = new HashSet<Object>(
|
||||
Arrays.asList(new String[] {
|
||||
BusProperties.BATCH_BUFFER_LIMIT,
|
||||
BinderProperties.BATCH_BUFFER_LIMIT,
|
||||
}));
|
||||
|
||||
private final List<Binding> bindings = Collections.synchronizedList(new ArrayList<Binding>());
|
||||
@@ -188,7 +188,7 @@ public abstract class MessageBusSupport
|
||||
|
||||
protected volatile int defaultMaxAttempts = DEFAULT_MAX_ATTEMPTS;
|
||||
|
||||
// properties for bus implementations that support batching
|
||||
// properties for binder implementations that support batching
|
||||
|
||||
protected volatile boolean defaultBatchingEnabled = false;
|
||||
|
||||
@@ -208,7 +208,7 @@ public abstract class MessageBusSupport
|
||||
private volatile Map<String, Class<?>> payloadTypeCache = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* For bus implementations that support a prefix, apply the prefix to the name.
|
||||
* For binder implementations that support a prefix, apply the prefix to the name.
|
||||
* @param prefix the prefix.
|
||||
* @param name the name.
|
||||
*/
|
||||
@@ -217,7 +217,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* For bus implementations that include a pub/sub component in identifiers, construct the name.
|
||||
* For binder implementations that include a pub/sub component in identifiers, construct the name.
|
||||
* @param name the name.
|
||||
*/
|
||||
public static String applyPubSub(String name) {
|
||||
@@ -234,7 +234,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* For bus implementations that support dead lettering, construct the name of the dead letter entity for the
|
||||
* For binder implementations that support dead lettering, construct the name of the dead letter entity for the
|
||||
* underlying pipe name.
|
||||
* @param name the name.
|
||||
*/
|
||||
@@ -269,7 +269,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the partition strategy to be used by this bus if no partitionExpression is provided for a module.
|
||||
* Set the partition strategy to be used by this binder if no partitionExpression is provided for a module.
|
||||
* @param partitionSelector The selector.
|
||||
*/
|
||||
public void setPartitionSelector(PartitionSelectorStrategy partitionSelector) {
|
||||
@@ -277,7 +277,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default retry back off initial interval for this bus; can be overridden with consumer
|
||||
* Set the default retry back off initial interval for this binder; can be overridden with consumer
|
||||
* 'backOffInitialInterval' property.
|
||||
* @param defaultBackOffInitialInterval
|
||||
*/
|
||||
@@ -286,7 +286,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default retry back off multiplier for this bus; can be overridden with consumer 'backOffMultiplier'
|
||||
* Set the default retry back off multiplier for this binder; can be overridden with consumer 'backOffMultiplier'
|
||||
* property.
|
||||
* @param defaultBackOffMultiplier
|
||||
*/
|
||||
@@ -295,7 +295,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default retry back off max interval for this bus; can be overridden with consumer 'backOffMaxInterval'
|
||||
* Set the default retry back off max interval for this binder; can be overridden with consumer 'backOffMaxInterval'
|
||||
* property.
|
||||
* @param defaultBackOffMaxInterval
|
||||
*/
|
||||
@@ -304,7 +304,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default concurrency for this bus; can be overridden with consumer 'concurrency' property.
|
||||
* Set the default concurrency for this binder; can be overridden with consumer 'concurrency' property.
|
||||
* @param defaultConcurrency
|
||||
*/
|
||||
public void setDefaultConcurrency(int defaultConcurrency) {
|
||||
@@ -312,7 +312,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* The default maximum delivery attempts for this bus. Can be overridden by consumer property 'maxAttempts' if
|
||||
* The default maximum delivery attempts for this binder. Can be overridden by consumer property 'maxAttempts' if
|
||||
* supported. Values less than 2 disable retry and one delivery attempt is made.
|
||||
* @param defaultMaxAttempts The default maximum attempts.
|
||||
*/
|
||||
@@ -321,7 +321,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether this bus batches message sends by default. Only applies to bus implementations that support
|
||||
* Set whether this binder batches message sends by default. Only applies to binder implementations that support
|
||||
* batching.
|
||||
* @param defaultBatchingEnabled the defaultBatchingEnabled to set.
|
||||
*/
|
||||
@@ -330,7 +330,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default batch size; only applies when batching is enabled and the bus supports batching.
|
||||
* Set the default batch size; only applies when batching is enabled and the binder supports batching.
|
||||
* @param defaultBatchSize the defaultBatchSize to set.
|
||||
*/
|
||||
public void setDefaultBatchSize(int defaultBatchSize) {
|
||||
@@ -339,7 +339,7 @@ public abstract class MessageBusSupport
|
||||
|
||||
/**
|
||||
* Set the default batch buffer limit - used to send a batch early if its size exceeds this. Only applies if
|
||||
* batching is enabled and the bus supports this property.
|
||||
* batching is enabled and the binder supports this property.
|
||||
* @param defaultBatchBufferLimit the defaultBatchBufferLimit to set.
|
||||
*/
|
||||
public void setDefaultBatchBufferLimit(int defaultBatchBufferLimit) {
|
||||
@@ -348,7 +348,7 @@ public abstract class MessageBusSupport
|
||||
|
||||
/**
|
||||
* Set the default batch timeout - used to send a batch if no messages arrive during this time. Only applies if
|
||||
* batching is enabled and the bus supports this property.
|
||||
* batching is enabled and the binder supports this property.
|
||||
* @param defaultBatchTimeout the defaultBatchTimeout to set.
|
||||
*/
|
||||
public void setDefaultBatchTimeout(long defaultBatchTimeout) {
|
||||
@@ -395,7 +395,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a producer for the named channel and bind it to the bus. Synchronized to avoid creating multiple
|
||||
* Create a producer for the named channel and bind it to the binder. Synchronized to avoid creating multiple
|
||||
* instances.
|
||||
* @param name The name.
|
||||
* @param channelName The name of the channel to be created, and registered as bean.
|
||||
@@ -412,7 +412,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
destroyCreatedChannel(channelName, channel);
|
||||
throw new MessageBusException(
|
||||
throw new BinderException(
|
||||
"Failed to bind dynamic channel '" + name + "' with properties " + properties, e);
|
||||
}
|
||||
}
|
||||
@@ -421,8 +421,8 @@ public abstract class MessageBusSupport
|
||||
|
||||
/**
|
||||
* Dynamically create a producer for the named channel. Note: even though it's pub/sub, we still use a direct
|
||||
* channel. It will be bridged to a pub/sub channel in the local bus and bound to an appropriate element for other
|
||||
* buses.
|
||||
* channel. It will be bridged to a pub/sub channel in the local binder and bound to an appropriate element for other
|
||||
* binders.
|
||||
* @param name The name.
|
||||
* @param properties The properties.
|
||||
* @return The channel.
|
||||
@@ -433,7 +433,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a producer for the named channel and bind it to the bus. Synchronized to avoid creating multiple
|
||||
* Create a producer for the named channel and bind it to the binder. Synchronized to avoid creating multiple
|
||||
* instances.
|
||||
* @param name The name.
|
||||
* @param channelName The name of the channel to be created, and registered as bean.
|
||||
@@ -450,7 +450,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
destroyCreatedChannel(channelName, channel);
|
||||
throw new MessageBusException(
|
||||
throw new BinderException(
|
||||
"Failed to bind dynamic channel '" + name + "' with properties " + properties, e);
|
||||
}
|
||||
}
|
||||
@@ -569,7 +569,7 @@ public abstract class MessageBusSupport
|
||||
messageValues.setPayload(payload);
|
||||
messageValues.put(MessageHeaders.CONTENT_TYPE, contentType);
|
||||
if (originalContentType != null) {
|
||||
messageValues.put(XdHeaders.XD_ORIGINAL_CONTENT_TYPE, originalContentType);
|
||||
messageValues.put(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE, originalContentType);
|
||||
}
|
||||
return messageValues;
|
||||
}
|
||||
@@ -588,7 +588,7 @@ public abstract class MessageBusSupport
|
||||
return bos.toByteArray();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new SerializationException("unable to serialize payload ["
|
||||
throw new SerializationFailedException("unable to serialize payload ["
|
||||
+ originalPayload.getClass().getName() + "]", e);
|
||||
}
|
||||
}
|
||||
@@ -606,9 +606,9 @@ public abstract class MessageBusSupport
|
||||
if (payload != null) {
|
||||
messageToSend.setPayload(payload);
|
||||
|
||||
Object originalContentType = messageToSend.get(XdHeaders.XD_ORIGINAL_CONTENT_TYPE);
|
||||
Object originalContentType = messageToSend.get(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE);
|
||||
messageToSend.put(MessageHeaders.CONTENT_TYPE, originalContentType);
|
||||
messageToSend.put(XdHeaders.XD_ORIGINAL_CONTENT_TYPE, null);
|
||||
messageToSend.put(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE, null);
|
||||
}
|
||||
return messageToSend;
|
||||
}
|
||||
@@ -631,7 +631,8 @@ public abstract class MessageBusSupport
|
||||
return new String(bytes, "UTF-8");
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
throw new SerializationException("unable to deserialize [java.lang.String]. Encoding not supported.", e);
|
||||
throw new SerializationFailedException("unable to deserialize [java.lang.String]. Encoding not supported.",
|
||||
e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -644,10 +645,13 @@ public abstract class MessageBusSupport
|
||||
payloadTypeCache.put(className, targetType);
|
||||
}
|
||||
return codec.deserialize(bytes, targetType);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new SerializationException("unable to deserialize [" + className + "]. Class not found.", e);//NOSONAR
|
||||
} catch (IOException e) {
|
||||
throw new SerializationException("unable to deserialize [" + className + "]", e);
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
throw new SerializationFailedException("unable to deserialize [" + className + "]. Class not found.",
|
||||
e);//NOSONAR
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new SerializationFailedException("unable to deserialize [" + className + "]", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -658,7 +662,7 @@ public abstract class MessageBusSupport
|
||||
* partition selector class is provided, it will be invoked to determine the partition. Otherwise, if the partition
|
||||
* expression is not null, it is evaluated against the key and is expected to return an integer to which the modulo
|
||||
* function will be applied, using the partitionCount as the divisor. If no partition expression is provided, the
|
||||
* key will be passed to the bus partition strategy along with the partitionCount. The default partition strategy
|
||||
* key will be passed to the binder partition strategy along with the partitionCount. The default partition strategy
|
||||
* uses {@code key.hashCode()}, and the result will be the mod of that value.
|
||||
* @param message the message.
|
||||
* @param meta the partitioning metadata.
|
||||
@@ -701,7 +705,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.error("Failed to load key extractor", e);
|
||||
throw new MessageBusException("Failed to load key extractor: " + partitionKeyExtractorClassName, e);
|
||||
throw new BinderException("Failed to load key extractor: " + partitionKeyExtractorClassName, e);
|
||||
}
|
||||
try {
|
||||
Object extractor = clazz.newInstance();
|
||||
@@ -712,7 +716,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.error("Failed to instantiate key extractor", e);
|
||||
throw new MessageBusException("Failed to instantiate key extractor: " + partitionKeyExtractorClassName, e);
|
||||
throw new BinderException("Failed to instantiate key extractor: " + partitionKeyExtractorClassName, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -727,7 +731,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.error("Failed to load partition selector", e);
|
||||
throw new MessageBusException("Failed to load partition selector: " + partitionSelectorClassName, e);
|
||||
throw new BinderException("Failed to load partition selector: " + partitionSelectorClassName, e);
|
||||
}
|
||||
try {
|
||||
Object extractor = clazz.newInstance();
|
||||
@@ -738,14 +742,14 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.error("Failed to instantiate partition selector", e);
|
||||
throw new MessageBusException("Failed to instantiate partition selector: " + partitionSelectorClassName,
|
||||
throw new BinderException("Failed to instantiate partition selector: " + partitionSelectorClassName,
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the provided deployment properties for the consumer against those supported by this bus implementation.
|
||||
* The consumer is that part of the bus that consumes messages from the underlying infrastructure and sends them to
|
||||
* Validate the provided deployment properties for the consumer against those supported by this binder implementation.
|
||||
* The consumer is that part of the binder that consumes messages from the underlying infrastructure and sends them to
|
||||
* the next module. Consumer properties are used to configure the consumer.
|
||||
* @param name The name.
|
||||
* @param properties The properties.
|
||||
@@ -758,8 +762,8 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the provided deployment properties for the producer against those supported by this bus implementation.
|
||||
* When a module sends a message to the bus, the producer uses these properties while sending it to the underlying
|
||||
* Validate the provided deployment properties for the producer against those supported by this binder implementation.
|
||||
* When a module sends a message to the binder, the producer uses these properties while sending it to the underlying
|
||||
* infrastructure.
|
||||
* @param name The name.
|
||||
* @param properties The properties.
|
||||
@@ -799,7 +803,7 @@ public abstract class MessageBusSupport
|
||||
* @param properties The properties.
|
||||
* @return The retry template, or null if retry is not enabled.
|
||||
*/
|
||||
protected RetryTemplate buildRetryTemplateIfRetryEnabled(AbstractBusPropertiesAccessor properties) {
|
||||
protected RetryTemplate buildRetryTemplateIfRetryEnabled(AbstractBinderPropertiesAccessor properties) {
|
||||
int maxAttempts = properties.getMaxAttempts(this.defaultMaxAttempts);
|
||||
if (maxAttempts > 1) {
|
||||
RetryTemplate template = new RetryTemplate();
|
||||
@@ -824,7 +828,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to create a direct binding (avoiding the bus) if the consumer is local. Named channel producers are not
|
||||
* Attempt to create a direct binding (avoiding the binder) if the consumer is local. Named channel producers are not
|
||||
* bound directly.
|
||||
* @param name The name.
|
||||
* @param moduleOutputChannel The channel to bind.
|
||||
@@ -832,7 +836,7 @@ public abstract class MessageBusSupport
|
||||
* @return true if the producer is bound.
|
||||
*/
|
||||
protected boolean bindNewProducerDirectlyIfPossible(String name, SubscribableChannel moduleOutputChannel,
|
||||
AbstractBusPropertiesAccessor properties) {
|
||||
AbstractBinderPropertiesAccessor properties) {
|
||||
if (!properties.isDirectBindingAllowed()) {
|
||||
return false;
|
||||
}
|
||||
@@ -865,7 +869,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
|
||||
private void bindProducerDirectly(String name, SubscribableChannel producerChannel,
|
||||
MessageChannel consumerChannel, AbstractBusPropertiesAccessor properties) {
|
||||
MessageChannel consumerChannel, AbstractBinderPropertiesAccessor properties) {
|
||||
DirectHandler handler = new DirectHandler(consumerChannel);
|
||||
EventDrivenConsumer consumer = new EventDrivenConsumer(producerChannel, handler);
|
||||
consumer.setBeanFactory(getBeanFactory());
|
||||
@@ -880,8 +884,8 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to bind a producer directly (avoiding the bus) if there is already a local producer. PubSub producers
|
||||
* cannot be bound directly. Create the direct binding, then unbind the existing bus producer.
|
||||
* Attempt to bind a producer directly (avoiding the binder) if there is already a local producer. PubSub producers
|
||||
* cannot be bound directly. Create the direct binding, then unbind the existing binder producer.
|
||||
* @param name The name.
|
||||
* @param consumerChannel The channel to bind the producer to.
|
||||
*/
|
||||
@@ -896,7 +900,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
}
|
||||
if (producerBinding != null && producerBinding.getChannel() instanceof SubscribableChannel) {
|
||||
AbstractBusPropertiesAccessor properties = producerBinding.getPropertiesAccessor();
|
||||
AbstractBinderPropertiesAccessor properties = producerBinding.getPropertiesAccessor();
|
||||
if (properties.isDirectBindingAllowed()) {
|
||||
bindProducerDirectly(name, (SubscribableChannel) producerBinding.getChannel(), consumerChannel,
|
||||
properties);
|
||||
@@ -966,7 +970,7 @@ public abstract class MessageBusSupport
|
||||
|
||||
private final int partitionCount;
|
||||
|
||||
public PartitioningMetadata(AbstractBusPropertiesAccessor properties, int partitionCount) {
|
||||
public PartitioningMetadata(AbstractBinderPropertiesAccessor properties, int partitionCount) {
|
||||
this.partitionCount = partitionCount;
|
||||
this.partitionKeyExtractorClass = properties.getPartitionKeyExtractorClass();
|
||||
this.partitionKeyExpression = properties.getPartitionKeyExpression();
|
||||
@@ -1039,7 +1043,8 @@ public abstract class MessageBusSupport
|
||||
*/
|
||||
abstract static class JavaClassMimeTypeConversion {
|
||||
|
||||
public static final MimeType APPLICATION_OCTET_STREAM_MIME_TYPE = MimeType.valueOf(APPLICATION_OCTET_STREAM_VALUE);
|
||||
public static final MimeType APPLICATION_OCTET_STREAM_MIME_TYPE = MimeType.valueOf
|
||||
(APPLICATION_OCTET_STREAM_VALUE);
|
||||
|
||||
public static final MimeType TEXT_PLAIN_MIME_TYPE = MimeType.valueOf(TEXT_PLAIN_VALUE);
|
||||
|
||||
@@ -1125,7 +1130,7 @@ public abstract class MessageBusSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform manual acknowledgement based on the metadata stored in message bus.
|
||||
* Perform manual acknowledgement based on the metadata stored in the binder.
|
||||
*/
|
||||
public void doManualAck(LinkedList<MessageHeaders> messageHeaders) {
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@@ -26,7 +26,7 @@ import org.springframework.messaging.Message;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A mutable type for allowing {@link MessageBus} implementations to transform and enrich message content more
|
||||
* A mutable type for allowing {@link Binder} implementations to transform and enrich message content more
|
||||
* efficiently.
|
||||
* @author David Turanski
|
||||
*/
|
||||
@@ -46,7 +46,7 @@ public class MessageValues implements Map<String, Object> {
|
||||
}
|
||||
}
|
||||
|
||||
public MessageValues(Object payload, Map<String,Object> headers) {
|
||||
public MessageValues(Object payload, Map<String, Object> headers) {
|
||||
this.payload = payload;
|
||||
this.headers.putAll(headers);
|
||||
}
|
||||
@@ -145,8 +145,8 @@ public class MessageValues implements Map<String, Object> {
|
||||
return headers.entrySet();
|
||||
}
|
||||
|
||||
public void copyHeadersIfAbsent(Map<String,Object> headersToCopy) {
|
||||
for (Entry<String, Object> headersToCopyEntry : headersToCopy.entrySet()) {
|
||||
public void copyHeadersIfAbsent(Map<String, Object> headersToCopy) {
|
||||
for (Entry<String, Object> headersToCopyEntry : headersToCopy.entrySet()) {
|
||||
if (!containsKey(headersToCopyEntry.getKey())) {
|
||||
put(headersToCopyEntry.getKey(), headersToCopyEntry.getValue());
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
|
||||
/**
|
||||
@@ -14,19 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
|
||||
import org.springframework.cloud.stream.exception.CloudStreamsRuntimeException;
|
||||
|
||||
/**
|
||||
* Exceptions thrown while interfacing with the RabbitMQ admin plugin.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 1.2
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class RabbitAdminException extends CloudStreamsRuntimeException {
|
||||
public class RabbitAdminException extends RuntimeException {
|
||||
|
||||
public RabbitAdminException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binder-test</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>spring-cloud-stream-binder-test</name>
|
||||
<description>Test support for binder implementations</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binders-parent</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<spring-amqp.version>1.4.5.RELEASE</spring-amqp.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-test</artifactId>
|
||||
<version>${spring-integration.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.avro</groupId>
|
||||
<artifactId>avro-compiler</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>${spring-framework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.xd</groupId>
|
||||
<artifactId>spring-xd-tuple</artifactId>
|
||||
<version>${spring-xd.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.xd</groupId>
|
||||
<artifactId>spring-xd-codec</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binder-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-codec</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -33,7 +33,7 @@ import org.springframework.integration.channel.interceptor.WireTap;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageBus.Capability;
|
||||
import org.springframework.cloud.stream.binder.Binder.Capability;
|
||||
import org.springframework.xd.dirt.integration.bus.serializer.MultiTypeCodec;
|
||||
import org.springframework.xd.dirt.integration.bus.serializer.kryo.PojoCodec;
|
||||
|
||||
@@ -49,92 +49,92 @@ import static org.junit.Assert.fail;
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @author David Turanski
|
||||
*/
|
||||
public abstract class AbstractMessageBusTests {
|
||||
public abstract class AbstractBinderTests {
|
||||
|
||||
protected static final Collection<MediaType> ALL = Collections.singletonList(MediaType.ALL);
|
||||
|
||||
protected AbstractTestMessageBus<?> testMessageBus;
|
||||
protected AbstractTestBinder<?> testBinder;
|
||||
|
||||
@Test
|
||||
public void testClean() throws Exception {
|
||||
MessageBus messageBus = getMessageBus();
|
||||
messageBus.bindProducer("foo.0", new DirectChannel(), null);
|
||||
messageBus.bindConsumer("foo.0", new DirectChannel(), null);
|
||||
messageBus.bindProducer("foo.1", new DirectChannel(), null);
|
||||
messageBus.bindConsumer("foo.1", new DirectChannel(), null);
|
||||
messageBus.bindProducer("foo.2", new DirectChannel(), null);
|
||||
Collection<?> bindings = getBindings(messageBus);
|
||||
Binder binder = getBinder();
|
||||
binder.bindProducer("foo.0", new DirectChannel(), null);
|
||||
binder.bindConsumer("foo.0", new DirectChannel(), null);
|
||||
binder.bindProducer("foo.1", new DirectChannel(), null);
|
||||
binder.bindConsumer("foo.1", new DirectChannel(), null);
|
||||
binder.bindProducer("foo.2", new DirectChannel(), null);
|
||||
Collection<?> bindings = getBindings(binder);
|
||||
assertEquals(5, bindings.size());
|
||||
messageBus.unbindProducers("foo.0");
|
||||
binder.unbindProducers("foo.0");
|
||||
assertEquals(4, bindings.size());
|
||||
messageBus.unbindConsumers("foo.0");
|
||||
messageBus.unbindProducers("foo.1");
|
||||
binder.unbindConsumers("foo.0");
|
||||
binder.unbindProducers("foo.1");
|
||||
assertEquals(2, bindings.size());
|
||||
messageBus.unbindConsumers("foo.1");
|
||||
messageBus.unbindProducers("foo.2");
|
||||
binder.unbindConsumers("foo.1");
|
||||
binder.unbindProducers("foo.2");
|
||||
assertTrue(bindings.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendAndReceive() throws Exception {
|
||||
MessageBus messageBus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
DirectChannel moduleOutputChannel = new DirectChannel();
|
||||
QueueChannel moduleInputChannel = new QueueChannel();
|
||||
messageBus.bindProducer("foo.0", moduleOutputChannel, null);
|
||||
messageBus.bindConsumer("foo.0", moduleInputChannel, null);
|
||||
binder.bindProducer("foo.0", moduleOutputChannel, null);
|
||||
binder.bindConsumer("foo.0", moduleInputChannel, null);
|
||||
Message<?> message = MessageBuilder.withPayload("foo").setHeader(MessageHeaders.CONTENT_TYPE,
|
||||
"foo/bar").build();
|
||||
// Let the consumer actually bind to the producer before sending a msg
|
||||
busBindUnbindLatency();
|
||||
binderBindUnbindLatency();
|
||||
moduleOutputChannel.send(message);
|
||||
Message<?> inbound = moduleInputChannel.receive(5000);
|
||||
assertNotNull(inbound);
|
||||
assertEquals("foo", inbound.getPayload());
|
||||
assertNull(inbound.getHeaders().get(XdHeaders.XD_ORIGINAL_CONTENT_TYPE));
|
||||
assertNull(inbound.getHeaders().get(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE));
|
||||
assertEquals("foo/bar", inbound.getHeaders().get(MessageHeaders.CONTENT_TYPE));
|
||||
messageBus.unbindProducers("foo.0");
|
||||
messageBus.unbindConsumers("foo.0");
|
||||
binder.unbindProducers("foo.0");
|
||||
binder.unbindConsumers("foo.0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendAndReceiveNoOriginalContentType() throws Exception {
|
||||
MessageBus messageBus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
DirectChannel moduleOutputChannel = new DirectChannel();
|
||||
QueueChannel moduleInputChannel = new QueueChannel();
|
||||
messageBus.bindProducer("bar.0", moduleOutputChannel, null);
|
||||
messageBus.bindConsumer("bar.0", moduleInputChannel, null);
|
||||
busBindUnbindLatency();
|
||||
binder.bindProducer("bar.0", moduleOutputChannel, null);
|
||||
binder.bindConsumer("bar.0", moduleInputChannel, null);
|
||||
binderBindUnbindLatency();
|
||||
|
||||
Message<?> message = MessageBuilder.withPayload("foo").build();
|
||||
moduleOutputChannel.send(message);
|
||||
Message<?> inbound = moduleInputChannel.receive(5000);
|
||||
assertNotNull(inbound);
|
||||
assertEquals("foo", inbound.getPayload());
|
||||
assertNull(inbound.getHeaders().get(XdHeaders.XD_ORIGINAL_CONTENT_TYPE));
|
||||
assertNull(inbound.getHeaders().get(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE));
|
||||
assertNull(inbound.getHeaders().get(MessageHeaders.CONTENT_TYPE));
|
||||
messageBus.unbindProducers("bar.0");
|
||||
messageBus.unbindConsumers("bar.0");
|
||||
binder.unbindProducers("bar.0");
|
||||
binder.unbindConsumers("bar.0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendAndReceivePubSub() throws Exception {
|
||||
MessageBus messageBus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
DirectChannel moduleOutputChannel = new DirectChannel();
|
||||
// Test pub/sub by emulating how StreamPlugin handles taps
|
||||
DirectChannel tapChannel = new DirectChannel();
|
||||
QueueChannel moduleInputChannel = new QueueChannel();
|
||||
QueueChannel module2InputChannel = new QueueChannel();
|
||||
QueueChannel module3InputChannel = new QueueChannel();
|
||||
messageBus.bindProducer("baz.0", moduleOutputChannel, null);
|
||||
messageBus.bindConsumer("baz.0", moduleInputChannel, null);
|
||||
binder.bindProducer("baz.0", moduleOutputChannel, null);
|
||||
binder.bindConsumer("baz.0", moduleInputChannel, null);
|
||||
moduleOutputChannel.addInterceptor(new WireTap(tapChannel));
|
||||
messageBus.bindPubSubProducer("tap:baz.http", tapChannel, null);
|
||||
binder.bindPubSubProducer("tap:baz.http", tapChannel, null);
|
||||
// A new module is using the tap as an input channel
|
||||
String fooTapName = messageBus.isCapable(Capability.DURABLE_PUBSUB) ? "foo.tap:baz.http" : "tap:baz.http";
|
||||
messageBus.bindPubSubConsumer(fooTapName, module2InputChannel, null);
|
||||
String fooTapName = binder.isCapable(Capability.DURABLE_PUBSUB) ? "foo.tap:baz.http" : "tap:baz.http";
|
||||
binder.bindPubSubConsumer(fooTapName, module2InputChannel, null);
|
||||
// Another new module is using tap as an input channel
|
||||
String barTapName = messageBus.isCapable(Capability.DURABLE_PUBSUB) ? "bar.tap:baz.http" : "tap:baz.http";
|
||||
messageBus.bindPubSubConsumer(barTapName, module3InputChannel, null);
|
||||
String barTapName = binder.isCapable(Capability.DURABLE_PUBSUB) ? "bar.tap:baz.http" : "tap:baz.http";
|
||||
binder.bindPubSubConsumer(barTapName, module3InputChannel, null);
|
||||
Message<?> message = MessageBuilder.withPayload("foo").setHeader(MessageHeaders.CONTENT_TYPE,
|
||||
"foo/bar").build();
|
||||
boolean success = false;
|
||||
@@ -144,7 +144,7 @@ public abstract class AbstractMessageBusTests {
|
||||
Message<?> inbound = moduleInputChannel.receive(5000);
|
||||
assertNotNull(inbound);
|
||||
assertEquals("foo", inbound.getPayload());
|
||||
assertNull(inbound.getHeaders().get(XdHeaders.XD_ORIGINAL_CONTENT_TYPE));
|
||||
assertNull(inbound.getHeaders().get(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE));
|
||||
assertEquals("foo/bar", inbound.getHeaders().get(MessageHeaders.CONTENT_TYPE));
|
||||
Message<?> tapped1 = module2InputChannel.receive(5000);
|
||||
Message<?> tapped2 = module3InputChannel.receive(5000);
|
||||
@@ -156,14 +156,14 @@ public abstract class AbstractMessageBusTests {
|
||||
}
|
||||
success = true;
|
||||
assertEquals("foo", tapped1.getPayload());
|
||||
assertNull(tapped1.getHeaders().get(XdHeaders.XD_ORIGINAL_CONTENT_TYPE));
|
||||
assertNull(tapped1.getHeaders().get(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE));
|
||||
assertEquals("foo/bar", tapped1.getHeaders().get(MessageHeaders.CONTENT_TYPE));
|
||||
assertEquals("foo", tapped2.getPayload());
|
||||
assertNull(tapped2.getHeaders().get(XdHeaders.XD_ORIGINAL_CONTENT_TYPE));
|
||||
assertNull(tapped2.getHeaders().get(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE));
|
||||
assertEquals("foo/bar", tapped2.getHeaders().get(MessageHeaders.CONTENT_TYPE));
|
||||
}
|
||||
// delete one tap stream is deleted
|
||||
messageBus.unbindConsumer(barTapName, module3InputChannel);
|
||||
binder.unbindConsumer(barTapName, module3InputChannel);
|
||||
Message<?> message2 = MessageBuilder.withPayload("bar").setHeader(MessageHeaders.CONTENT_TYPE,
|
||||
"foo/bar").build();
|
||||
moduleOutputChannel.send(message2);
|
||||
@@ -176,17 +176,17 @@ public abstract class AbstractMessageBusTests {
|
||||
assertNull(module3InputChannel.receive(1000));
|
||||
|
||||
// when other tap stream is deleted
|
||||
messageBus.unbindConsumer(fooTapName, module2InputChannel);
|
||||
binder.unbindConsumer(fooTapName, module2InputChannel);
|
||||
// Clean up as StreamPlugin would
|
||||
messageBus.unbindConsumer("baz.0", moduleInputChannel);
|
||||
messageBus.unbindProducer("baz.0", moduleOutputChannel);
|
||||
messageBus.unbindProducers("tap:baz.http");
|
||||
assertTrue(getBindings(messageBus).isEmpty());
|
||||
binder.unbindConsumer("baz.0", moduleInputChannel);
|
||||
binder.unbindProducer("baz.0", moduleOutputChannel);
|
||||
binder.unbindProducers("tap:baz.http");
|
||||
assertTrue(getBindings(binder).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createInboundPubSubBeforeOutboundPubSub() throws Exception {
|
||||
MessageBus messageBus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
DirectChannel moduleOutputChannel = new DirectChannel();
|
||||
// Test pub/sub by emulating how StreamPlugin handles taps
|
||||
DirectChannel tapChannel = new DirectChannel();
|
||||
@@ -194,18 +194,18 @@ public abstract class AbstractMessageBusTests {
|
||||
QueueChannel module2InputChannel = new QueueChannel();
|
||||
QueueChannel module3InputChannel = new QueueChannel();
|
||||
// Create the tap first
|
||||
String fooTapName = messageBus.isCapable(Capability.DURABLE_PUBSUB) ? "foo.tap:baz.http" : "tap:baz.http";
|
||||
messageBus.bindPubSubConsumer(fooTapName, module2InputChannel, null);
|
||||
String fooTapName = binder.isCapable(Capability.DURABLE_PUBSUB) ? "foo.tap:baz.http" : "tap:baz.http";
|
||||
binder.bindPubSubConsumer(fooTapName, module2InputChannel, null);
|
||||
|
||||
// Then create the stream
|
||||
messageBus.bindProducer("baz.0", moduleOutputChannel, null);
|
||||
messageBus.bindConsumer("baz.0", moduleInputChannel, null);
|
||||
binder.bindProducer("baz.0", moduleOutputChannel, null);
|
||||
binder.bindConsumer("baz.0", moduleInputChannel, null);
|
||||
moduleOutputChannel.addInterceptor(new WireTap(tapChannel));
|
||||
messageBus.bindPubSubProducer("tap:baz.http", tapChannel, null);
|
||||
binder.bindPubSubProducer("tap:baz.http", tapChannel, null);
|
||||
|
||||
// Another new module is using tap as an input channel
|
||||
String barTapName = messageBus.isCapable(Capability.DURABLE_PUBSUB) ? "bar.tap:baz.http" : "tap:baz.http";
|
||||
messageBus.bindPubSubConsumer(barTapName, module3InputChannel, null);
|
||||
String barTapName = binder.isCapable(Capability.DURABLE_PUBSUB) ? "bar.tap:baz.http" : "tap:baz.http";
|
||||
binder.bindPubSubConsumer(barTapName, module3InputChannel, null);
|
||||
Message<?> message = MessageBuilder.withPayload("foo").setHeader(MessageHeaders.CONTENT_TYPE,
|
||||
"foo/bar").build();
|
||||
boolean success = false;
|
||||
@@ -215,7 +215,7 @@ public abstract class AbstractMessageBusTests {
|
||||
Message<?> inbound = moduleInputChannel.receive(5000);
|
||||
assertNotNull(inbound);
|
||||
assertEquals("foo", inbound.getPayload());
|
||||
assertNull(inbound.getHeaders().get(XdHeaders.XD_ORIGINAL_CONTENT_TYPE));
|
||||
assertNull(inbound.getHeaders().get(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE));
|
||||
assertEquals("foo/bar", inbound.getHeaders().get(MessageHeaders.CONTENT_TYPE));
|
||||
Message<?> tapped1 = module2InputChannel.receive(5000);
|
||||
Message<?> tapped2 = module3InputChannel.receive(5000);
|
||||
@@ -227,14 +227,14 @@ public abstract class AbstractMessageBusTests {
|
||||
}
|
||||
success = true;
|
||||
assertEquals("foo", tapped1.getPayload());
|
||||
assertNull(tapped1.getHeaders().get(XdHeaders.XD_ORIGINAL_CONTENT_TYPE));
|
||||
assertNull(tapped1.getHeaders().get(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE));
|
||||
assertEquals("foo/bar", tapped1.getHeaders().get(MessageHeaders.CONTENT_TYPE));
|
||||
assertEquals("foo", tapped2.getPayload());
|
||||
assertNull(tapped2.getHeaders().get(XdHeaders.XD_ORIGINAL_CONTENT_TYPE));
|
||||
assertNull(tapped2.getHeaders().get(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE));
|
||||
assertEquals("foo/bar", tapped2.getHeaders().get(MessageHeaders.CONTENT_TYPE));
|
||||
}
|
||||
// delete one tap stream is deleted
|
||||
messageBus.unbindConsumer(barTapName, module3InputChannel);
|
||||
binder.unbindConsumer(barTapName, module3InputChannel);
|
||||
Message<?> message2 = MessageBuilder.withPayload("bar").setHeader(MessageHeaders.CONTENT_TYPE,
|
||||
"foo/bar").build();
|
||||
moduleOutputChannel.send(message2);
|
||||
@@ -247,43 +247,43 @@ public abstract class AbstractMessageBusTests {
|
||||
assertNull(module3InputChannel.receive(1000));
|
||||
|
||||
// when other tap stream is deleted
|
||||
messageBus.unbindConsumer(fooTapName, module2InputChannel);
|
||||
binder.unbindConsumer(fooTapName, module2InputChannel);
|
||||
// Clean up as StreamPlugin would
|
||||
messageBus.unbindConsumer("baz.0", moduleInputChannel);
|
||||
messageBus.unbindProducer("baz.0", moduleOutputChannel);
|
||||
messageBus.unbindProducers("tap:baz.http");
|
||||
assertTrue(getBindings(messageBus).isEmpty());
|
||||
binder.unbindConsumer("baz.0", moduleInputChannel);
|
||||
binder.unbindProducer("baz.0", moduleOutputChannel);
|
||||
binder.unbindProducers("tap:baz.http");
|
||||
assertTrue(getBindings(binder).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadDynamic() throws Exception {
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty(BusProperties.PARTITION_KEY_EXPRESSION, "'foo'");
|
||||
MessageBus messageBus = getMessageBus();
|
||||
properties.setProperty(BinderProperties.PARTITION_KEY_EXPRESSION, "'foo'");
|
||||
Binder binder = getBinder();
|
||||
try {
|
||||
messageBus.bindDynamicProducer("queue:foo", properties);
|
||||
binder.bindDynamicProducer("queue:foo", properties);
|
||||
fail("Exception expected");
|
||||
}
|
||||
catch (MessageBusException mbe) {
|
||||
catch (BinderException mbe) {
|
||||
Assert.assertEquals("Failed to bind dynamic channel 'queue:foo' with properties " +
|
||||
"{partitionKeyExpression='foo'}",
|
||||
mbe.getMessage());
|
||||
if (messageBus instanceof AbstractTestMessageBus) {
|
||||
messageBus = ((AbstractTestMessageBus) messageBus).getCoreMessageBus();
|
||||
if (binder instanceof AbstractTestBinder) {
|
||||
binder = ((AbstractTestBinder) binder).getCoreBinder();
|
||||
}
|
||||
assertFalse(((MessageBusSupport) messageBus).getApplicationContext().containsBean("queue:foo"));
|
||||
assertFalse(((MessageChannelBinderSupport) binder).getApplicationContext().containsBean("queue:foo"));
|
||||
}
|
||||
}
|
||||
|
||||
protected Collection<?> getBindings(MessageBus testMessageBus) {
|
||||
if (testMessageBus instanceof AbstractTestMessageBus) {
|
||||
return getBindingsFromMsgBus(((AbstractTestMessageBus) testMessageBus).getCoreMessageBus());
|
||||
protected Collection<?> getBindings(Binder testBinder) {
|
||||
if (testBinder instanceof AbstractTestBinder) {
|
||||
return getBindingsFromBinder(((AbstractTestBinder) testBinder).getCoreBinder());
|
||||
}
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
protected Collection<?> getBindingsFromMsgBus(MessageBus messageBus) {
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(messageBus);
|
||||
protected Collection<?> getBindingsFromBinder(Binder binder) {
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(binder);
|
||||
return (List<?>) accessor.getPropertyValue("bindings");
|
||||
}
|
||||
|
||||
@@ -292,19 +292,19 @@ public abstract class AbstractMessageBusTests {
|
||||
return new PojoCodec();
|
||||
}
|
||||
|
||||
protected abstract MessageBus getMessageBus() throws Exception;
|
||||
protected abstract Binder getBinder() throws Exception;
|
||||
|
||||
@After
|
||||
public void cleanup() {
|
||||
if (testMessageBus != null) {
|
||||
testMessageBus.cleanup();
|
||||
if (testBinder != null) {
|
||||
testBinder.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If appropriate, let the bus middleware settle down a bit while binding/unbinding actually happens.
|
||||
* If appropriate, let the binder middleware settle down a bit while binding/unbinding actually happens.
|
||||
*/
|
||||
protected void busBindUnbindLatency() throws InterruptedException {
|
||||
protected void binderBindUnbindLatency() throws InterruptedException {
|
||||
// default none
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.test;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
@@ -25,65 +25,65 @@ import org.springframework.messaging.MessageChannel;
|
||||
|
||||
|
||||
/**
|
||||
* Abstract class that adds test support for {@link MessageBus}.
|
||||
* Abstract class that adds test support for {@link Binder}.
|
||||
*
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public abstract class AbstractTestMessageBus<C extends MessageBusSupport> implements MessageBus {
|
||||
public abstract class AbstractTestBinder<C extends MessageChannelBinderSupport> implements Binder<MessageChannel> {
|
||||
|
||||
protected Set<String> queues = new HashSet<String>();
|
||||
|
||||
protected Set<String> topics = new HashSet<String>();
|
||||
|
||||
private C messageBus;
|
||||
private C binder;
|
||||
|
||||
public void setMessageBus(C messageBus) {
|
||||
messageBus.setIntegrationEvaluationContext(new StandardEvaluationContext());
|
||||
public void setBinder(C binder) {
|
||||
binder.setIntegrationEvaluationContext(new StandardEvaluationContext());
|
||||
try {
|
||||
messageBus.afterPropertiesSet();
|
||||
binder.afterPropertiesSet();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException("Failed to initialize message bus", e);
|
||||
throw new RuntimeException("Failed to initialize binder", e);
|
||||
}
|
||||
this.messageBus = messageBus;
|
||||
this.binder = binder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindConsumer(String name, MessageChannel moduleInputChannel, Properties properties) {
|
||||
messageBus.bindConsumer(name, moduleInputChannel, properties);
|
||||
binder.bindConsumer(name, moduleInputChannel, properties);
|
||||
queues.add(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindPubSubConsumer(String name, MessageChannel inputChannel, Properties properties) {
|
||||
messageBus.bindPubSubConsumer(name, inputChannel, properties);
|
||||
binder.bindPubSubConsumer(name, inputChannel, properties);
|
||||
addTopic(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindProducer(String name, MessageChannel moduleOutputChannel, Properties properties) {
|
||||
messageBus.bindProducer(name, moduleOutputChannel, properties);
|
||||
binder.bindProducer(name, moduleOutputChannel, properties);
|
||||
queues.add(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindPubSubProducer(String name, MessageChannel outputChannel, Properties properties) {
|
||||
messageBus.bindPubSubProducer(name, outputChannel, properties);
|
||||
binder.bindPubSubProducer(name, outputChannel, properties);
|
||||
addTopic(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindRequestor(String name, MessageChannel requests, MessageChannel replies,
|
||||
Properties properties) {
|
||||
messageBus.bindRequestor(name, requests, replies, properties);
|
||||
binder.bindRequestor(name, requests, replies, properties);
|
||||
queues.add(name + ".requests");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindReplier(String name, MessageChannel requests, MessageChannel replies,
|
||||
Properties properties) {
|
||||
messageBus.bindReplier(name, requests, replies, properties);
|
||||
binder.bindReplier(name, requests, replies, properties);
|
||||
queues.add(name + ".requests");
|
||||
}
|
||||
|
||||
@@ -91,51 +91,51 @@ public abstract class AbstractTestMessageBus<C extends MessageBusSupport> implem
|
||||
topics.add("topic." + topicName);
|
||||
}
|
||||
|
||||
public C getCoreMessageBus() {
|
||||
return messageBus;
|
||||
public C getCoreBinder() {
|
||||
return binder;
|
||||
}
|
||||
|
||||
public abstract void cleanup();
|
||||
|
||||
@Override
|
||||
public void unbindConsumers(String name) {
|
||||
messageBus.unbindConsumers(name);
|
||||
binder.unbindConsumers(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbindProducers(String name) {
|
||||
messageBus.unbindProducers(name);
|
||||
binder.unbindProducers(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbindConsumer(String name, MessageChannel channel) {
|
||||
messageBus.unbindConsumer(name, channel);
|
||||
binder.unbindConsumer(name, channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbindProducer(String name, MessageChannel channel) {
|
||||
messageBus.unbindProducer(name, channel);
|
||||
binder.unbindProducer(name, channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageChannel bindDynamicProducer(String name, Properties properties) {
|
||||
this.queues.add(name);
|
||||
return this.messageBus.bindDynamicProducer(name, properties);
|
||||
return this.binder.bindDynamicProducer(name, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageChannel bindDynamicPubSubProducer(String name, Properties properties) {
|
||||
this.topics.add(name);
|
||||
return this.messageBus.bindDynamicPubSubProducer(name, properties);
|
||||
return this.binder.bindDynamicPubSubProducer(name, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCapable(Capability capability) {
|
||||
return this.messageBus.isCapable(capability);
|
||||
return this.binder.isCapable(capability);
|
||||
}
|
||||
|
||||
public MessageBus getMessageBus() {
|
||||
return this.messageBus;
|
||||
public Binder getBinder() {
|
||||
return this.binder;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -30,7 +30,7 @@ import org.springframework.integration.support.utils.IntegrationUtils;
|
||||
*
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public class BusTestUtils {
|
||||
public class BinderTestUtils {
|
||||
|
||||
private static final MessageBuilderFactory mbf = new DefaultMessageBuilderFactory();
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@@ -35,25 +35,25 @@ import org.springframework.messaging.support.GenericMessage;
|
||||
|
||||
|
||||
/**
|
||||
* Tests for buses that use an external broker.
|
||||
* Tests for binders that use an external broker.
|
||||
*
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public abstract class BrokerBusTests extends
|
||||
AbstractMessageBusTests {
|
||||
public abstract class BrokerBinderTests extends
|
||||
AbstractBinderTests {
|
||||
|
||||
@Test
|
||||
public void testDirectBinding() throws Exception {
|
||||
MessageBus bus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty(BusProperties.DIRECT_BINDING_ALLOWED, "true");
|
||||
properties.setProperty(BinderProperties.DIRECT_BINDING_ALLOWED, "true");
|
||||
|
||||
DirectChannel moduleInputChannel = new DirectChannel();
|
||||
moduleInputChannel.setBeanName("direct.input");
|
||||
DirectChannel moduleOutputChannel = new DirectChannel();
|
||||
moduleOutputChannel.setBeanName("direct.output");
|
||||
bus.bindConsumer("direct.0", moduleInputChannel, null);
|
||||
bus.bindProducer("direct.0", moduleOutputChannel, properties);
|
||||
binder.bindConsumer("direct.0", moduleInputChannel, null);
|
||||
binder.bindProducer("direct.0", moduleOutputChannel, properties);
|
||||
|
||||
final AtomicReference<Thread> caller = new AtomicReference<Thread>();
|
||||
final AtomicInteger count = new AtomicInteger();
|
||||
@@ -74,9 +74,9 @@ AbstractMessageBusTests {
|
||||
assertEquals(2, count.get());
|
||||
assertNull(spyOn("direct.0").receive(true));
|
||||
|
||||
// Remove direct binding and bind producer to the bus
|
||||
bus.unbindConsumers("direct.0");
|
||||
busBindUnbindLatency();
|
||||
// Remove direct binding and bind producer to the binder
|
||||
binder.unbindConsumers("direct.0");
|
||||
binderBindUnbindLatency();
|
||||
|
||||
Spy spy = spyOn("direct.0");
|
||||
count.set(0);
|
||||
@@ -88,9 +88,9 @@ AbstractMessageBusTests {
|
||||
assertEquals("baz", baz);
|
||||
assertEquals(0, count.get());
|
||||
|
||||
// Unbind producer from bus and bind directly again
|
||||
// Unbind producer from binder and bind directly again
|
||||
caller.set(null);
|
||||
bus.bindConsumer("direct.0", moduleInputChannel, null);
|
||||
binder.bindConsumer("direct.0", moduleInputChannel, null);
|
||||
moduleOutputChannel.send(new GenericMessage<String>("foo"));
|
||||
moduleOutputChannel.send(new GenericMessage<String>("foo"));
|
||||
assertNotNull(caller.get());
|
||||
@@ -98,8 +98,8 @@ AbstractMessageBusTests {
|
||||
assertEquals(2, count.get());
|
||||
assertNull(spy.receive(true));
|
||||
|
||||
bus.unbindProducers("direct.0");
|
||||
bus.unbindConsumers("direct.0");
|
||||
binder.unbindProducers("direct.0");
|
||||
binder.unbindConsumers("direct.0");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
@@ -41,30 +41,29 @@ import org.springframework.integration.endpoint.AbstractEndpoint;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.xd.test.TestUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Tests for buses that support partitioning.
|
||||
* Tests for binders that support partitioning.
|
||||
*
|
||||
* @author Gary Russell
|
||||
*/
|
||||
abstract public class PartitionCapableBusTests extends BrokerBusTests {
|
||||
abstract public class PartitionCapableBinderTests extends BrokerBinderTests {
|
||||
|
||||
@Test
|
||||
public void testBadProperties() throws Exception {
|
||||
MessageBus bus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
Properties properties = new Properties();
|
||||
properties.put("foo", "bar");
|
||||
properties.put("baz", "qux");
|
||||
|
||||
DirectChannel output = new DirectChannel();
|
||||
try {
|
||||
bus.bindProducer("badprops.0", output, properties);
|
||||
binder.bindProducer("badprops.0", output, properties);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), allOf(Matchers.containsString(bus.getClass().getSimpleName().replace("Test", "")
|
||||
+ " does not support producer "),
|
||||
assertThat(e.getMessage(), allOf(Matchers.containsString(getClassUnderTestName()
|
||||
+ " does not support producer "),
|
||||
containsString("foo"),
|
||||
containsString("baz"),
|
||||
containsString(" for badprops.0.")));
|
||||
@@ -72,28 +71,28 @@ abstract public class PartitionCapableBusTests extends BrokerBusTests {
|
||||
|
||||
properties.remove("baz");
|
||||
try {
|
||||
bus.bindConsumer("badprops.0", output, properties);
|
||||
binder.bindConsumer("badprops.0", output, properties);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), equalTo(bus.getClass().getSimpleName().replace("Test", "")
|
||||
assertThat(e.getMessage(), equalTo(getClassUnderTestName()
|
||||
+ " does not support consumer property: foo for badprops.0."));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPartitionedModuleSpEL() throws Exception {
|
||||
MessageBus bus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
Properties properties = new Properties();
|
||||
properties.put("partitionKeyExpression", "payload");
|
||||
properties.put("partitionSelectorExpression", "hashCode()");
|
||||
properties.put(BusProperties.NEXT_MODULE_COUNT, "3");
|
||||
properties.put(BusProperties.NEXT_MODULE_CONCURRENCY, "2");
|
||||
properties.put(BinderProperties.NEXT_MODULE_COUNT, "3");
|
||||
properties.put(BinderProperties.NEXT_MODULE_CONCURRENCY, "2");
|
||||
|
||||
DirectChannel output = new DirectChannel();
|
||||
output.setBeanName("test.output");
|
||||
bus.bindProducer("part.0", output, properties);
|
||||
binder.bindProducer("part.0", output, properties);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(bus, "messageBus.bindings", List.class);
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(binder, "binder.bindings", List.class);
|
||||
assertEquals(1, bindings.size());
|
||||
try {
|
||||
AbstractEndpoint endpoint = bindings.get(0).getEndpoint();
|
||||
@@ -109,21 +108,21 @@ abstract public class PartitionCapableBusTests extends BrokerBusTests {
|
||||
properties.put("count","3");
|
||||
QueueChannel input0 = new QueueChannel();
|
||||
input0.setBeanName("test.input0S");
|
||||
bus.bindConsumer("part.0", input0, properties);
|
||||
binder.bindConsumer("part.0", input0, properties);
|
||||
properties.put("partitionIndex", "1");
|
||||
QueueChannel input1 = new QueueChannel();
|
||||
input1.setBeanName("test.input1S");
|
||||
bus.bindConsumer("part.0", input1, properties);
|
||||
binder.bindConsumer("part.0", input1, properties);
|
||||
properties.put("partitionIndex", "2");
|
||||
QueueChannel input2 = new QueueChannel();
|
||||
input2.setBeanName("test.input2S");
|
||||
bus.bindConsumer("part.0", input2, properties);
|
||||
binder.bindConsumer("part.0", input2, properties);
|
||||
|
||||
Message<Integer> message2 = MessageBuilder.withPayload(2)
|
||||
.setHeader(IntegrationMessageHeaderAccessor.CORRELATION_ID, "foo")
|
||||
.setHeader(IntegrationMessageHeaderAccessor.SEQUENCE_NUMBER, 42)
|
||||
.setHeader(IntegrationMessageHeaderAccessor.SEQUENCE_SIZE, 43)
|
||||
.setHeader("xdReplyChannel", "bar")
|
||||
.setHeader(BinderHeaders.BINDER_REPLY_CHANNEL, "bar")
|
||||
.build();
|
||||
output.send(message2);
|
||||
output.send(new GenericMessage<Integer>(1));
|
||||
@@ -144,7 +143,7 @@ abstract public class PartitionCapableBusTests extends BrokerBusTests {
|
||||
boolean result = "foo".equals(accessor.getCorrelationId()) &&
|
||||
42 == accessor.getSequenceNumber() &&
|
||||
43 == accessor.getSequenceSize() &&
|
||||
"bar".equals(accessor.getHeader("xdReplyChannel"));
|
||||
"bar".equals(accessor.getHeader(BinderHeaders.BINDER_REPLY_CHANNEL));
|
||||
return result;
|
||||
}
|
||||
};
|
||||
@@ -177,24 +176,24 @@ abstract public class PartitionCapableBusTests extends BrokerBusTests {
|
||||
|
||||
}
|
||||
|
||||
bus.unbindConsumers("part.0");
|
||||
bus.unbindProducers("part.0");
|
||||
binder.unbindConsumers("part.0");
|
||||
binder.unbindProducers("part.0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPartitionedModuleJava() throws Exception {
|
||||
MessageBus bus = getMessageBus();
|
||||
Binder binder = getBinder();
|
||||
Properties properties = new Properties();
|
||||
properties.put("partitionKeyExtractorClass", "org.springframework.xd.dirt.integration.bus.PartitionTestSupport");
|
||||
properties.put("partitionSelectorClass", "org.springframework.xd.dirt.integration.bus.PartitionTestSupport");
|
||||
properties.put(BusProperties.NEXT_MODULE_COUNT, "3");
|
||||
properties.put(BusProperties.NEXT_MODULE_CONCURRENCY, "2");
|
||||
properties.put("partitionKeyExtractorClass", "org.springframework.cloud.stream.binder.PartitionTestSupport");
|
||||
properties.put("partitionSelectorClass", "org.springframework.cloud.stream.binder.PartitionTestSupport");
|
||||
properties.put(BinderProperties.NEXT_MODULE_COUNT, "3");
|
||||
properties.put(BinderProperties.NEXT_MODULE_CONCURRENCY, "2");
|
||||
|
||||
DirectChannel output = new DirectChannel();
|
||||
output.setBeanName("test.output");
|
||||
bus.bindProducer("partJ.0", output, properties);
|
||||
binder.bindProducer("partJ.0", output, properties);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(bus, "messageBus.bindings", List.class);
|
||||
List<Binding> bindings = TestUtils.getPropertyValue(binder, "binder.bindings", List.class);
|
||||
assertEquals(1, bindings.size());
|
||||
if (usesExplicitRouting()) {
|
||||
AbstractEndpoint endpoint = bindings.get(0).getEndpoint();
|
||||
@@ -207,15 +206,15 @@ abstract public class PartitionCapableBusTests extends BrokerBusTests {
|
||||
properties.put("partitionIndex", "0");
|
||||
QueueChannel input0 = new QueueChannel();
|
||||
input0.setBeanName("test.input0J");
|
||||
bus.bindConsumer("partJ.0", input0, properties);
|
||||
binder.bindConsumer("partJ.0", input0, properties);
|
||||
properties.put("partitionIndex", "1");
|
||||
QueueChannel input1 = new QueueChannel();
|
||||
input1.setBeanName("test.input1J");
|
||||
bus.bindConsumer("partJ.0", input1, properties);
|
||||
binder.bindConsumer("partJ.0", input1, properties);
|
||||
properties.put("partitionIndex", "2");
|
||||
QueueChannel input2 = new QueueChannel();
|
||||
input2.setBeanName("test.input2J");
|
||||
bus.bindConsumer("partJ.0", input2, properties);
|
||||
binder.bindConsumer("partJ.0", input2, properties);
|
||||
|
||||
output.send(new GenericMessage<Integer>(2));
|
||||
output.send(new GenericMessage<Integer>(1));
|
||||
@@ -242,12 +241,12 @@ abstract public class PartitionCapableBusTests extends BrokerBusTests {
|
||||
containsInAnyOrder(0, 1, 2));
|
||||
}
|
||||
|
||||
bus.unbindConsumers("partJ.0");
|
||||
bus.unbindProducers("partJ.0");
|
||||
binder.unbindConsumers("partJ.0");
|
||||
binder.unbindProducers("partJ.0");
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementations should return whether the bus under test uses "explicit" routing (e.g. Rabbit)
|
||||
* Implementations should return whether the binder under test uses "explicit" routing (e.g. Rabbit)
|
||||
* whereby XD is responsible for assigning a partition and knows which exact consumer will receive the
|
||||
* message (i.e. honor "partitionIndex") or "implicit" routing (e.g. Kafka) whereby the only guarantee
|
||||
* is that messages will be spread, but we don't control exactly which consumer gets which message.
|
||||
@@ -267,5 +266,7 @@ abstract public class PartitionCapableBusTests extends BrokerBusTests {
|
||||
protected String getPubSubEndpointRouting(AbstractEndpoint endpoint) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
protected abstract String getClassUnderTestName();
|
||||
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
/**
|
||||
* Represents an out-of-band connection to the underlying middleware,
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.xd.test;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
@@ -31,7 +31,7 @@ import org.springframework.messaging.converter.ContentTypeResolver;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageBusSupport.JavaClassMimeTypeConversion;
|
||||
import org.springframework.cloud.stream.binder.MessageChannelBinderSupport.JavaClassMimeTypeConversion;
|
||||
import org.springframework.xd.dirt.integration.bus.serializer.kryo.PojoCodec;
|
||||
import org.springframework.xd.tuple.DefaultTuple;
|
||||
import org.springframework.xd.tuple.Tuple;
|
||||
@@ -46,33 +46,33 @@ import static org.junit.Assert.assertSame;
|
||||
* @author Gary Russell
|
||||
* @author David Turanski
|
||||
*/
|
||||
public class MessageBusSupportTests {
|
||||
public class MessageChannelBinderSupportTests {
|
||||
|
||||
private ContentTypeResolver contentTypeResolver = new StringConvertingContentTypeResolver();
|
||||
|
||||
private final TestMessageBus messageBus = new TestMessageBus();
|
||||
private final TestMessageChannelBinder binder = new TestMessageChannelBinder();
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Before
|
||||
public void setUp() {
|
||||
messageBus.setCodec(new PojoCodec(new TupleKryoRegistrar()));
|
||||
binder.setCodec(new PojoCodec(new TupleKryoRegistrar()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBytesPassThru() {
|
||||
byte[] payload = "foo".getBytes();
|
||||
Message<byte[]> message = MessageBuilder.withPayload(payload).build();
|
||||
MessageValues converted = messageBus.serializePayloadIfNecessary(message
|
||||
MessageValues converted = binder.serializePayloadIfNecessary(message
|
||||
);
|
||||
assertSame(payload, converted.getPayload());
|
||||
Message<?> convertedMessage = converted.toMessage();
|
||||
assertSame(payload, convertedMessage.getPayload());
|
||||
assertEquals(MimeTypeUtils.APPLICATION_OCTET_STREAM,
|
||||
contentTypeResolver.resolve(convertedMessage.getHeaders()));
|
||||
MessageValues reconstructed = messageBus.deserializePayloadIfNecessary(convertedMessage);
|
||||
MessageValues reconstructed = binder.deserializePayloadIfNecessary(convertedMessage);
|
||||
payload = (byte[]) reconstructed.getPayload();
|
||||
assertSame(converted.getPayload(), payload);
|
||||
assertNull(reconstructed.get(XdHeaders.XD_ORIGINAL_CONTENT_TYPE));
|
||||
assertNull(reconstructed.get(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -81,29 +81,29 @@ public class MessageBusSupportTests {
|
||||
Message<byte[]> message = MessageBuilder.withPayload(payload)
|
||||
.setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE)
|
||||
.build();
|
||||
MessageValues messageValues = messageBus.serializePayloadIfNecessary(message
|
||||
MessageValues messageValues = binder.serializePayloadIfNecessary(message
|
||||
);
|
||||
Message<?> converted = messageValues.toMessage();
|
||||
assertSame(payload, converted.getPayload());
|
||||
assertEquals(MimeTypeUtils.APPLICATION_OCTET_STREAM,
|
||||
contentTypeResolver.resolve(converted.getHeaders()));
|
||||
MessageValues reconstructed = messageBus.deserializePayloadIfNecessary(converted);
|
||||
MessageValues reconstructed = binder.deserializePayloadIfNecessary(converted);
|
||||
payload = (byte[]) reconstructed.getPayload();
|
||||
assertSame(converted.getPayload(), payload);
|
||||
assertEquals(MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE,
|
||||
reconstructed.get(MessageHeaders.CONTENT_TYPE));
|
||||
assertNull(reconstructed.get(XdHeaders.XD_ORIGINAL_CONTENT_TYPE));
|
||||
assertNull(reconstructed.get(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testString() throws IOException {
|
||||
MessageValues convertedValues = messageBus.serializePayloadIfNecessary(
|
||||
MessageValues convertedValues = binder.serializePayloadIfNecessary(
|
||||
new GenericMessage<String>("foo"));
|
||||
|
||||
Message<?> converted = convertedValues.toMessage();
|
||||
assertEquals(MimeTypeUtils.TEXT_PLAIN,
|
||||
contentTypeResolver.resolve(converted.getHeaders()));
|
||||
MessageValues reconstructed = messageBus.deserializePayloadIfNecessary(converted);
|
||||
MessageValues reconstructed = binder.deserializePayloadIfNecessary(converted);
|
||||
assertEquals("foo", reconstructed.getPayload());
|
||||
assertNull(reconstructed.get(MessageHeaders.CONTENT_TYPE));
|
||||
}
|
||||
@@ -113,7 +113,7 @@ public class MessageBusSupportTests {
|
||||
Message<String> inbound = MessageBuilder.withPayload("{\"foo\":\"foo\"}")
|
||||
.copyHeaders(Collections.singletonMap(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON))
|
||||
.build();
|
||||
MessageValues convertedValues = messageBus.serializePayloadIfNecessary(
|
||||
MessageValues convertedValues = binder.serializePayloadIfNecessary(
|
||||
inbound);
|
||||
|
||||
Message<?> converted = convertedValues.toMessage();
|
||||
@@ -121,15 +121,15 @@ public class MessageBusSupportTests {
|
||||
assertEquals(MimeTypeUtils.TEXT_PLAIN,
|
||||
contentTypeResolver.resolve(converted.getHeaders()));
|
||||
assertEquals(MimeTypeUtils.APPLICATION_JSON,
|
||||
converted.getHeaders().get(XdHeaders.XD_ORIGINAL_CONTENT_TYPE));
|
||||
MessageValues reconstructed = messageBus.deserializePayloadIfNecessary(converted);
|
||||
converted.getHeaders().get(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE));
|
||||
MessageValues reconstructed = binder.deserializePayloadIfNecessary(converted);
|
||||
assertEquals("{\"foo\":\"foo\"}", reconstructed.getPayload());
|
||||
assertEquals(MimeTypeUtils.APPLICATION_JSON, reconstructed.get(MessageHeaders.CONTENT_TYPE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPojoSerialization() {
|
||||
MessageValues convertedValues = messageBus.serializePayloadIfNecessary(
|
||||
MessageValues convertedValues = binder.serializePayloadIfNecessary(
|
||||
new GenericMessage<Foo>(new Foo("bar"))
|
||||
);
|
||||
Message<?> converted = convertedValues.toMessage();
|
||||
@@ -138,14 +138,14 @@ public class MessageBusSupportTests {
|
||||
assertEquals("x-java-object", mimeType.getSubtype());
|
||||
assertEquals(Foo.class.getName(), mimeType.getParameter("type"));
|
||||
|
||||
MessageValues reconstructed = messageBus.deserializePayloadIfNecessary(converted);
|
||||
MessageValues reconstructed = binder.deserializePayloadIfNecessary(converted);
|
||||
assertEquals("bar", ((Foo) reconstructed.getPayload()).getBar());
|
||||
assertNull(reconstructed.get(MessageHeaders.CONTENT_TYPE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPojoWithXJavaObjectMimeTypeNoType() {
|
||||
MessageValues convertedValues = messageBus.serializePayloadIfNecessary(
|
||||
MessageValues convertedValues = binder.serializePayloadIfNecessary(
|
||||
new GenericMessage<Foo>(new Foo("bar"))
|
||||
);
|
||||
Message<?> converted = convertedValues.toMessage();
|
||||
@@ -154,14 +154,14 @@ public class MessageBusSupportTests {
|
||||
assertEquals("x-java-object", mimeType.getSubtype());
|
||||
assertEquals(Foo.class.getName(), mimeType.getParameter("type"));
|
||||
|
||||
MessageValues reconstructed = messageBus.deserializePayloadIfNecessary(converted);
|
||||
MessageValues reconstructed = binder.deserializePayloadIfNecessary(converted);
|
||||
assertEquals("bar", ((Foo) reconstructed.getPayload()).getBar());
|
||||
assertNull(reconstructed.get(MessageHeaders.CONTENT_TYPE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPojoWithXJavaObjectMimeTypeExplicitType() {
|
||||
MessageValues convertedValues = messageBus.serializePayloadIfNecessary(
|
||||
MessageValues convertedValues = binder.serializePayloadIfNecessary(
|
||||
new GenericMessage<Foo>(new Foo("bar"))
|
||||
);
|
||||
Message<?> converted = convertedValues.toMessage();
|
||||
@@ -170,7 +170,7 @@ public class MessageBusSupportTests {
|
||||
assertEquals("x-java-object", mimeType.getSubtype());
|
||||
assertEquals(Foo.class.getName(), mimeType.getParameter("type"));
|
||||
|
||||
MessageValues reconstructed = messageBus.deserializePayloadIfNecessary(converted);
|
||||
MessageValues reconstructed = binder.deserializePayloadIfNecessary(converted);
|
||||
assertEquals("bar", ((Foo) reconstructed.getPayload()).getBar());
|
||||
assertNull(reconstructed.get(MessageHeaders.CONTENT_TYPE));
|
||||
}
|
||||
@@ -178,7 +178,7 @@ public class MessageBusSupportTests {
|
||||
@Test
|
||||
public void testTupleSerialization() {
|
||||
Tuple payload = TupleBuilder.tuple().of("foo", "bar");
|
||||
MessageValues convertedValues = messageBus.serializePayloadIfNecessary(new GenericMessage<Tuple>(payload)
|
||||
MessageValues convertedValues = binder.serializePayloadIfNecessary(new GenericMessage<Tuple>(payload)
|
||||
);
|
||||
Message<?> converted = convertedValues.toMessage();
|
||||
MimeType mimeType = contentTypeResolver.resolve(converted.getHeaders());
|
||||
@@ -186,7 +186,7 @@ public class MessageBusSupportTests {
|
||||
assertEquals("x-java-object", mimeType.getSubtype());
|
||||
assertEquals(DefaultTuple.class.getName(), mimeType.getParameter("type"));
|
||||
|
||||
MessageValues reconstructed = messageBus.deserializePayloadIfNecessary(converted);
|
||||
MessageValues reconstructed = binder.deserializePayloadIfNecessary(converted);
|
||||
assertEquals("bar", ((Tuple) reconstructed.getPayload()).getString("foo"));
|
||||
assertNull(reconstructed.get(MessageHeaders.CONTENT_TYPE));
|
||||
}
|
||||
@@ -268,7 +268,7 @@ public class MessageBusSupportTests {
|
||||
|
||||
}
|
||||
|
||||
public class TestMessageBus extends MessageBusSupport {
|
||||
public class TestMessageChannelBinder extends MessageChannelBinderSupport {
|
||||
|
||||
@Override
|
||||
public void bindConsumer(String name, MessageChannel channel, Properties properties) {
|
||||
@@ -1,5 +0,0 @@
|
||||
/**
|
||||
* This package contains an implementation of the {@link org.springframework.xd.dirt.integration.bus.MessageBus} for RabbitMQ.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.rabbit;
|
||||
@@ -1,5 +0,0 @@
|
||||
/**
|
||||
* This package contains an implementation of the {@link org.springframework.xd.dirt.integration.bus.MessageBus} for Redis.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.redis;
|
||||
@@ -1,120 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-test</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>spring-cloud-stream-binding-test</name>
|
||||
<description>Test support for binding implementations</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-bindings-parent</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<spring-amqp.version>1.4.5.RELEASE</spring-amqp.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<!-- There's no comparison with gradle's syntax, but I think we'll be happy sticking with
|
||||
maven for the superior dependency and project management -->
|
||||
|
||||
<!--
|
||||
compile ("org.springframework.integration:spring-integration-test"){
|
||||
exclude group: 'org.apache.avro', module: 'avro-compiler'
|
||||
|
||||
}
|
||||
compile "org.springframework.integration:spring-integration-amqp"
|
||||
compile "org.springframework.integration:spring-integration-redis"
|
||||
compile "org.springframework.integration:spring-integration-mqtt"
|
||||
compile ("org.springframework.integration:spring-integration-kafka:$springIntegrationKafkaVersion") {
|
||||
exclude group: 'org.apache.avro', module: 'avro-compiler'
|
||||
}
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-test</artifactId>
|
||||
<version>${spring-integration.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.avro</groupId>
|
||||
<artifactId>avro-compiler</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!--<dependency>-->
|
||||
<!--<groupId>org.springframework.integration</groupId>-->
|
||||
<!--<artifactId>spring-integration-redis</artifactId>-->
|
||||
<!--<version>${spring-integration.version}</version>-->
|
||||
<!--</dependency>-->
|
||||
<!--<dependency>-->
|
||||
<!--<groupId>org.springframework.integration</groupId>-->
|
||||
<!--<artifactId>spring-integration-mqtt</artifactId>-->
|
||||
<!--<version>${spring-integration.version}</version>-->
|
||||
<!--</dependency>-->
|
||||
<!--<dependency>-->
|
||||
<!--<groupId>org.springframework.integration</groupId>-->
|
||||
<!--<artifactId>spring-integration-kafka</artifactId>-->
|
||||
<!--<version>1.1.2.RELEASE</version>-->
|
||||
<!--<exclusions>-->
|
||||
<!--<exclusion>-->
|
||||
<!--<groupId>org.apache.avro</groupId>-->
|
||||
<!--<artifactId>avro-compiler</artifactId>-->
|
||||
<!--</exclusion>-->
|
||||
<!--</exclusions>-->
|
||||
<!--</dependency>-->
|
||||
<!--<dependency>-->
|
||||
<!--<groupId>org.apache.kafka</groupId>-->
|
||||
<!--<artifactId>kafka_2.10</artifactId>-->
|
||||
<!--</dependency>-->
|
||||
<!--<dependency>-->
|
||||
<!--<groupId>org.apache.kafka</groupId>-->
|
||||
<!--<artifactId>kafka_2.10</artifactId>-->
|
||||
<!--<classifier>test</classifier>-->
|
||||
<!--</dependency>-->
|
||||
<!--<dependency>-->
|
||||
<!--<groupId>org.apache.kafka</groupId>-->
|
||||
<!--<artifactId>kafka-clients</artifactId>-->
|
||||
<!--</dependency>-->
|
||||
<!--<dependency>-->
|
||||
<!--<groupId>org.apache.curator</groupId>-->
|
||||
<!--<artifactId>curator-test</artifactId>-->
|
||||
<!--</dependency>-->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>${spring-framework.version}</version>
|
||||
</dependency>
|
||||
<!--<dependency>-->
|
||||
<!--<groupId>org.springframework.amqp</groupId>-->
|
||||
<!--<artifactId>spring-rabbit</artifactId>-->
|
||||
<!--<version>${spring-amqp.version}</version>-->
|
||||
<!--</dependency>-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.xd</groupId>
|
||||
<artifactId>spring-xd-tuple</artifactId>
|
||||
<version>${spring-xd.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.xd</groupId>
|
||||
<artifactId>spring-xd-codec</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-codec</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -19,10 +19,6 @@
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.esotericsoftware</groupId>
|
||||
<artifactId>kryo-shaded</artifactId>
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 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.xd.dirt.integration.bus.serializer;
|
||||
|
||||
|
||||
import org.springframework.cloud.stream.exception.CloudStreamsRuntimeException;
|
||||
|
||||
/**
|
||||
* Thrown when something goes wrong with inter-module communication.
|
||||
*
|
||||
* @author David Turanski
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class SerializationException extends CloudStreamsRuntimeException {
|
||||
|
||||
public SerializationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public SerializationException(String message, Throwable t) {
|
||||
super(message, t);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import com.esotericsoftware.kryo.Registration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.xd.dirt.integration.bus.serializer.SerializationException;
|
||||
import org.springframework.core.serializer.support.SerializationFailedException;
|
||||
|
||||
/**
|
||||
* @author David Turanski
|
||||
@@ -38,7 +38,7 @@ public abstract class AbstractKryoRegistrar implements KryoRegistrar {
|
||||
register(kryo, registration);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public abstract List<Registration> getRegistrations();
|
||||
|
||||
protected void register(Kryo kryo, Registration registration) {
|
||||
@@ -47,11 +47,11 @@ public abstract class AbstractKryoRegistrar implements KryoRegistrar {
|
||||
Registration existing = kryo.getRegistration(id);
|
||||
|
||||
if (existing != null) {
|
||||
throw new SerializationException(String.format("registration already exists %s", existing));
|
||||
throw new SerializationFailedException(String.format("registration already exists %s", existing));
|
||||
}
|
||||
|
||||
log.info("registering {} with serializer {}", registration, registration.getSerializer().getClass()
|
||||
.getName());
|
||||
.getName());
|
||||
|
||||
kryo.register(registration);
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ import java.util.List;
|
||||
|
||||
import com.esotericsoftware.kryo.Registration;
|
||||
|
||||
import org.springframework.core.serializer.support.SerializationFailedException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.xd.dirt.integration.bus.serializer.SerializationException;
|
||||
|
||||
/**
|
||||
* A {@link KryoRegistrar} that delegates and validates
|
||||
@@ -37,7 +37,7 @@ public class CompositeKryoRegistrar extends AbstractKryoRegistrar {
|
||||
public CompositeKryoRegistrar(List<KryoRegistrar> delegates) {
|
||||
super();
|
||||
this.delegates = delegates;
|
||||
|
||||
|
||||
if (!CollectionUtils.isEmpty(this.delegates)) {
|
||||
validateRegistrations();
|
||||
}
|
||||
@@ -60,18 +60,18 @@ public class CompositeKryoRegistrar extends AbstractKryoRegistrar {
|
||||
Assert.isTrue(registration.getId() >= MIN_REGISTRATION_VALUE, "registration ID must be >= " +
|
||||
MIN_REGISTRATION_VALUE);
|
||||
if (ids.contains(registration.getId())) {
|
||||
throw new SerializationException(String.format("Duplicate registration ID found: %d",
|
||||
throw new SerializationFailedException(String.format("Duplicate registration ID found: %d",
|
||||
registration.getId()));
|
||||
}
|
||||
ids.add(registration.getId());
|
||||
|
||||
if (types.contains(registration.getType())) {
|
||||
throw new SerializationException(String.format("Duplicate registration found for type: %s",
|
||||
throw new SerializationFailedException(String.format("Duplicate registration found for type: %s",
|
||||
registration.getType()));
|
||||
}
|
||||
types.add(registration.getType());
|
||||
|
||||
log.info("configured Kryo registration {} with serializer {}", registration,
|
||||
log.info("configured Kryo registration {} with serializer {}", registration,
|
||||
registration.getSerializer().getClass().getName());
|
||||
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-cloud-stream-common</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>spring-cloud-stream-common</name>
|
||||
<description>Spring Cloud Streams common components</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-parent</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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.exception;
|
||||
|
||||
/**
|
||||
* @author David Turanski
|
||||
*/
|
||||
public class CloudStreamsRuntimeException extends RuntimeException {
|
||||
|
||||
public CloudStreamsRuntimeException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public CloudStreamsRuntimeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,7 +28,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-redis</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-redis</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-redis</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-redis</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-redis</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-redis</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
@@ -50,16 +50,16 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-local</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-local</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-redis</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binding-rabbit</artifactId>
|
||||
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.cloud.stream.binder.BinderHeaders;
|
||||
import org.springframework.cloud.stream.config.ChannelBindingProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
@@ -49,11 +50,10 @@ import org.springframework.messaging.core.DestinationResolver;
|
||||
import org.springframework.messaging.support.ChannelInterceptorAdapter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageBus;
|
||||
import org.springframework.xd.dirt.integration.bus.XdHeaders;
|
||||
import org.springframework.cloud.stream.binder.Binder;
|
||||
|
||||
/**
|
||||
* Binds input/output channels to the bus.
|
||||
* Binds input/output channels to the binder.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Dave Syer
|
||||
@@ -64,7 +64,8 @@ public class ChannelBindingAdapter implements Lifecycle, ApplicationContextAware
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(ChannelBindingAdapter.class);
|
||||
|
||||
private MessageBus messageBus;
|
||||
private Binder<MessageChannel> binder;
|
||||
|
||||
private MessageBuilderFactory messageBuilderFactory = new DefaultMessageBuilderFactory();
|
||||
|
||||
private Collection<OutputChannelBinding> outputChannels = Collections.emptySet();
|
||||
@@ -86,9 +87,9 @@ public class ChannelBindingAdapter implements Lifecycle, ApplicationContextAware
|
||||
|
||||
private Map<String, String> bindings = new HashMap<String, String>();
|
||||
|
||||
public ChannelBindingAdapter(ChannelBindingProperties module, MessageBus messageBus) {
|
||||
public ChannelBindingAdapter(ChannelBindingProperties module, Binder<MessageChannel> binder) {
|
||||
this.module = module;
|
||||
this.messageBus = messageBus;
|
||||
this.binder = binder;
|
||||
this.channelLocator = new DefaultChannelLocator(module);
|
||||
}
|
||||
|
||||
@@ -179,7 +180,7 @@ public class ChannelBindingAdapter implements Lifecycle, ApplicationContextAware
|
||||
return;
|
||||
}
|
||||
String tapChannelName = channel.getTapChannelName();
|
||||
this.messageBus.unbindProducers(tapChannelName);
|
||||
this.binder.unbindProducers(tapChannelName);
|
||||
channel.setTapped(false);
|
||||
}
|
||||
|
||||
@@ -239,17 +240,17 @@ public class ChannelBindingAdapter implements Lifecycle, ApplicationContextAware
|
||||
if (name == null) {
|
||||
continue;
|
||||
}
|
||||
this.messageBus.unbindConsumers(name);
|
||||
this.binder.unbindConsumers(name);
|
||||
}
|
||||
for (OutputChannelBinding binding : this.outputChannels) {
|
||||
String name = this.bindings.get(binding.getRemoteName());
|
||||
if (name == null) {
|
||||
continue;
|
||||
}
|
||||
this.messageBus.unbindProducers(name);
|
||||
this.binder.unbindProducers(name);
|
||||
if (binding.isTapped()) {
|
||||
String tapChannelName = binding.getTapChannelName();
|
||||
this.messageBus.unbindProducers(tapChannelName);
|
||||
this.binder.unbindProducers(tapChannelName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -322,20 +323,20 @@ public class ChannelBindingAdapter implements Lifecycle, ApplicationContextAware
|
||||
private void bindMessageConsumer(MessageChannel inputChannel,
|
||||
String inputChannelName, Properties consumerProperties) {
|
||||
if (isChannelPubSub(inputChannelName)) {
|
||||
this.messageBus.bindPubSubConsumer(inputChannelName, inputChannel, consumerProperties);
|
||||
this.binder.bindPubSubConsumer(inputChannelName, inputChannel, consumerProperties);
|
||||
}
|
||||
else {
|
||||
this.messageBus.bindConsumer(inputChannelName, inputChannel, consumerProperties);
|
||||
this.binder.bindConsumer(inputChannelName, inputChannel, consumerProperties);
|
||||
}
|
||||
}
|
||||
|
||||
private void bindMessageProducer(MessageChannel outputChannel,
|
||||
String outputChannelName, Properties producerProperties) {
|
||||
if (isChannelPubSub(outputChannelName)) {
|
||||
this.messageBus.bindPubSubProducer(outputChannelName, outputChannel, producerProperties);
|
||||
this.binder.bindPubSubProducer(outputChannelName, outputChannel, producerProperties);
|
||||
}
|
||||
else {
|
||||
this.messageBus.bindProducer(outputChannelName, outputChannel, producerProperties);
|
||||
this.binder.bindProducer(outputChannelName, outputChannel, producerProperties);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,7 +347,7 @@ public class ChannelBindingAdapter implements Lifecycle, ApplicationContextAware
|
||||
|
||||
/**
|
||||
* Creates a wiretap on the output channel and binds the tap channel to
|
||||
* {@link MessageBus}'s message target.
|
||||
* {@link org.springframework.cloud.stream.binder.Binder}'s message target.
|
||||
*
|
||||
* @param tapChannelName the name of the tap channel
|
||||
* @param localName the channel to tap
|
||||
@@ -357,7 +358,7 @@ public class ChannelBindingAdapter implements Lifecycle, ApplicationContextAware
|
||||
if (channel instanceof ChannelInterceptorAware) {
|
||||
DirectChannel tapChannel = new DirectChannel();
|
||||
tapChannel.setBeanName(tapChannelName + ".tap.bridge");
|
||||
this.messageBus.bindPubSubProducer(tapChannelName, tapChannel, null); // TODO
|
||||
this.binder.bindPubSubProducer(tapChannelName, tapChannel, null); // TODO
|
||||
// tap
|
||||
// producer
|
||||
// props
|
||||
@@ -384,7 +385,7 @@ public class ChannelBindingAdapter implements Lifecycle, ApplicationContextAware
|
||||
public Message<?> preSend(Message<?> message, MessageChannel channel) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Collection<Map<String, Object>> history = (Collection<Map<String, Object>>) message
|
||||
.getHeaders().get(XdHeaders.XD_HISTORY);
|
||||
.getHeaders().get(BinderHeaders.BINDER_HISTORY);
|
||||
if (history == null) {
|
||||
history = new ArrayList<Map<String, Object>>(1);
|
||||
}
|
||||
@@ -396,7 +397,7 @@ public class ChannelBindingAdapter implements Lifecycle, ApplicationContextAware
|
||||
map.put("thread", Thread.currentThread().getName());
|
||||
history.add(map);
|
||||
Message<?> out = ChannelBindingAdapter.this.messageBuilderFactory.fromMessage(message)
|
||||
.setHeader(XdHeaders.XD_HISTORY, history).build();
|
||||
.setHeader(BinderHeaders.BINDER_HISTORY, history).build();
|
||||
return out;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
@@ -24,19 +24,19 @@ import org.springframework.messaging.core.DestinationResolutionException;
|
||||
|
||||
/**
|
||||
* A {@link org.springframework.messaging.core.DestinationResolver} implementation that first checks for any channel
|
||||
* whose name begins with a colon in the {@link MessageBus}.
|
||||
* whose name begins with a colon in the {@link Binder}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public class MessageBusAwareChannelResolver extends BeanFactoryMessageChannelDestinationResolver {
|
||||
public class BinderAwareChannelResolver extends BeanFactoryMessageChannelDestinationResolver {
|
||||
|
||||
private final MessageBus messageBus;
|
||||
private final Binder<MessageChannel> binder;
|
||||
|
||||
private final Properties producerProperties;
|
||||
|
||||
public MessageBusAwareChannelResolver(MessageBus messageBus, Properties producerProperties) {
|
||||
this.messageBus = messageBus;
|
||||
public BinderAwareChannelResolver(Binder<MessageChannel> binder, Properties producerProperties) {
|
||||
this.binder = binder;
|
||||
this.producerProperties = producerProperties;
|
||||
}
|
||||
|
||||
@@ -49,14 +49,14 @@ public class MessageBusAwareChannelResolver extends BeanFactoryMessageChannelDes
|
||||
catch (DestinationResolutionException e) {
|
||||
}
|
||||
if (name.indexOf(":") != -1) {
|
||||
if (messageBus != null) {
|
||||
if (binder != null) {
|
||||
String[] tokens = name.split(":", 2);
|
||||
String type = tokens[0];
|
||||
if ("queue".equals(type)) {
|
||||
channel = this.messageBus.bindDynamicProducer(name, this.producerProperties);
|
||||
channel = this.binder.bindDynamicProducer(name, this.producerProperties);
|
||||
}
|
||||
else if ("topic".equals(type)) {
|
||||
channel = this.messageBus.bindDynamicPubSubProducer(name, this.producerProperties);
|
||||
channel = this.binder.bindDynamicPubSubProducer(name, this.producerProperties);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("unrecognized channel type: " + type);
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
@@ -25,18 +25,18 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.integration.router.AbstractMappingMessageRouter;
|
||||
|
||||
/**
|
||||
* A {@link BeanPostProcessor} that sets a {@link MessageBusAwareChannelResolver} on any bean of type
|
||||
* A {@link BeanPostProcessor} that sets a {@link BinderAwareChannelResolver} on any bean of type
|
||||
* {@link AbstractMappingMessageRouter} within the context.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public class MessageBusAwareRouterBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
|
||||
public class BinderAwareRouterBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
|
||||
|
||||
private final MessageBusAwareChannelResolver channelResolver;
|
||||
private final BinderAwareChannelResolver channelResolver;
|
||||
|
||||
public MessageBusAwareRouterBeanPostProcessor(MessageBus messageBus, Properties producerProperties) {
|
||||
this.channelResolver = new MessageBusAwareChannelResolver(messageBus, producerProperties);
|
||||
public BinderAwareRouterBeanPostProcessor(Binder binder, Properties producerProperties) {
|
||||
this.channelResolver = new BinderAwareChannelResolver(binder, producerProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -37,13 +37,13 @@ import org.springframework.cloud.stream.adapter.InputChannelBinding;
|
||||
import org.springframework.cloud.stream.adapter.OutputChannelBinding;
|
||||
import org.springframework.cloud.stream.annotation.Input;
|
||||
import org.springframework.cloud.stream.annotation.Output;
|
||||
import org.springframework.cloud.stream.binder.BinderAwareRouterBeanPostProcessor;
|
||||
import org.springframework.cloud.stream.endpoint.ChannelsEndpoint;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageBus;
|
||||
import org.springframework.xd.dirt.integration.bus.MessageBusAwareRouterBeanPostProcessor;
|
||||
import org.springframework.cloud.stream.binder.Binder;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
@@ -62,11 +62,11 @@ public class ChannelBindingAdapterConfiguration {
|
||||
private ChannelLocator channelLocator;
|
||||
|
||||
@Autowired
|
||||
private MessageBus messageBus;
|
||||
private Binder<MessageChannel> binder;
|
||||
|
||||
@Bean
|
||||
public ChannelBindingAdapter messageBusAdapter() {
|
||||
ChannelBindingAdapter adapter = new ChannelBindingAdapter(this.module, this.messageBus);
|
||||
public ChannelBindingAdapter binderAdapter() {
|
||||
ChannelBindingAdapter adapter = new ChannelBindingAdapter(this.module, this.binder);
|
||||
adapter.setOutputChannels(getOutputChannels());
|
||||
adapter.setInputChannels(getInputChannels());
|
||||
if (this.channelLocator != null) {
|
||||
@@ -81,7 +81,7 @@ public class ChannelBindingAdapterConfiguration {
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
ChannelBindingAdapter adapter = messageBusAdapter();
|
||||
ChannelBindingAdapter adapter = binderAdapter();
|
||||
adapter.setOutputChannels(getOutputChannels());
|
||||
adapter.setInputChannels(getInputChannels());
|
||||
}
|
||||
@@ -116,23 +116,23 @@ public class ChannelBindingAdapterConfiguration {
|
||||
|
||||
// Nested class to avoid instantiating all of the above early
|
||||
@Configuration
|
||||
protected static class MessageBusAwareRouterConfiguration {
|
||||
protected static class BinderAwareRouterConfiguration {
|
||||
|
||||
@Autowired
|
||||
private ListableBeanFactory beanFactory;
|
||||
|
||||
@Bean
|
||||
public MessageBusAwareRouterBeanPostProcessor messageBusAwareRouterBeanPostProcessor() {
|
||||
public BinderAwareRouterBeanPostProcessor binderAwareRouterBeanPostProcessor() {
|
||||
|
||||
return new MessageBusAwareRouterBeanPostProcessor(createLazyProxy(
|
||||
this.beanFactory, MessageBus.class), new Properties());
|
||||
return new BinderAwareRouterBeanPostProcessor(createLazyProxy(
|
||||
this.beanFactory, Binder.class), new Properties());
|
||||
}
|
||||
|
||||
private <T> T createLazyProxy(ListableBeanFactory beanFactory, Class<T> type) {
|
||||
ProxyFactory factory = new ProxyFactory();
|
||||
LazyInitTargetSource source = new LazyInitTargetSource();
|
||||
source.setTargetClass(type);
|
||||
source.setTargetBeanName(getBeanNameFor(beanFactory, MessageBus.class));
|
||||
source.setTargetBeanName(getBeanNameFor(beanFactory, Binder.class));
|
||||
source.setBeanFactory(beanFactory);
|
||||
factory.setTargetSource(source);
|
||||
factory.addAdvice(new PassthruAdvice());
|
||||
@@ -145,7 +145,7 @@ public class ChannelBindingAdapterConfiguration {
|
||||
private String getBeanNameFor(ListableBeanFactory beanFactory, Class<?> type) {
|
||||
String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
|
||||
beanFactory, type, false, false);
|
||||
Assert.state(names.length == 1, "No unique MessageBus (found " + names.length
|
||||
Assert.state(names.length == 1, "No unique Binder (found " + names.length
|
||||
+ ": " + Arrays.asList(names) + ")");
|
||||
return names[0];
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportResource;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.xd.dirt.integration.rabbit.RabbitMessageBus;
|
||||
import org.springframework.cloud.stream.binder.rabbit.RabbitMessageChannelBinder;
|
||||
|
||||
/**
|
||||
* Bind to services, either locally or in a Lattice environment.
|
||||
@@ -36,11 +36,11 @@ import org.springframework.xd.dirt.integration.rabbit.RabbitMessageBus;
|
||||
* @author Glenn Renfro
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(RabbitMessageBus.class)
|
||||
@ConditionalOnMissingBean(RabbitMessageBus.class)
|
||||
@ImportResource({ "classpath*:/META-INF/spring-xd/bus/rabbit-bus.xml",
|
||||
@ConditionalOnClass(RabbitMessageChannelBinder.class)
|
||||
@ConditionalOnMissingBean(RabbitMessageChannelBinder.class)
|
||||
@ImportResource({ "classpath*:/META-INF/spring-cloud-stream/binder/rabbit-binder.xml",
|
||||
"classpath*:/META-INF/spring-xd/analytics/rabbit-analytics.xml" })
|
||||
@PropertySource("classpath:/META-INF/spring-cloud-streams/rabbit-bus.properties")
|
||||
@PropertySource("classpath:/META-INF/spring-cloud-stream/rabbit-binder.properties")
|
||||
public class RabbitServiceConfiguration {
|
||||
@Configuration
|
||||
@Profile("cloud")
|
||||
|
||||
@@ -20,13 +20,13 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cloud.Cloud;
|
||||
import org.springframework.cloud.CloudFactory;
|
||||
import org.springframework.cloud.stream.binder.redis.RedisMessageChannelBinder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportResource;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.xd.dirt.integration.redis.RedisMessageBus;
|
||||
|
||||
/**
|
||||
* Bind to services, either locally or in a Lattice environment.
|
||||
@@ -35,11 +35,11 @@ import org.springframework.xd.dirt.integration.redis.RedisMessageBus;
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(RedisMessageBus.class)
|
||||
@ConditionalOnMissingBean(RedisMessageBus.class)
|
||||
@ImportResource({ "classpath*:/META-INF/spring-xd/bus/redis-bus.xml",
|
||||
@ConditionalOnClass(RedisMessageChannelBinder.class)
|
||||
@ConditionalOnMissingBean(RedisMessageChannelBinder.class)
|
||||
@ImportResource({ "classpath*:/META-INF/spring-cloud-stream/binder/redis-binder.xml",
|
||||
"classpath*:/META-INF/spring-xd/analytics/redis-analytics.xml" })
|
||||
@PropertySource("classpath:/META-INF/spring-cloud-streams/redis-bus.properties")
|
||||
@PropertySource("classpath:/META-INF/spring-cloud-stream/redis-binder.properties")
|
||||
public class RedisServiceConfiguration {
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#TODO: New naming convention
|
||||
xd.messagebus.rabbit.default.ackMode: AUTO
|
||||
xd.messagebus.rabbit.default.autoBindDLQ: false
|
||||
xd.messagebus.rabbit.default.backOffInitialInterval: 1000
|
||||
@@ -1,3 +1,4 @@
|
||||
#TODO: New naming convention
|
||||
xd.messagebus.redis.default.backOffInitialInterval: 1000
|
||||
xd.messagebus.redis.default.backOffMaxInterval: 10000
|
||||
xd.messagebus.redis.default.backOffMultiplier: 2.0
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.xd.dirt.integration.bus;
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
@@ -35,6 +35,7 @@ import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.cloud.stream.binder.local.LocalMessageChannelBinder;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.channel.PublishSubscribeChannel;
|
||||
@@ -48,26 +49,25 @@ import org.springframework.messaging.MessageHandler;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.scheduling.support.PeriodicTrigger;
|
||||
import org.springframework.xd.dirt.integration.bus.local.LocalMessageBus;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public class MessageBusAwareChannelResolverTests {
|
||||
public class BinderAwareChannelResolverTests {
|
||||
|
||||
private final StaticApplicationContext context = new StaticApplicationContext();
|
||||
|
||||
private volatile MessageBusAwareChannelResolver resolver;
|
||||
private volatile BinderAwareChannelResolver resolver;
|
||||
|
||||
private volatile LocalMessageBus bus;
|
||||
private volatile LocalMessageChannelBinder binder;
|
||||
|
||||
@Before
|
||||
public void setupContext() throws Exception {
|
||||
this.bus = new LocalMessageBus();
|
||||
this.bus.setApplicationContext(context);
|
||||
this.bus.afterPropertiesSet();
|
||||
this.resolver = new MessageBusAwareChannelResolver(this.bus, null);
|
||||
this.binder = new LocalMessageChannelBinder();
|
||||
this.binder.setApplicationContext(context);
|
||||
this.binder.afterPropertiesSet();
|
||||
this.resolver = new BinderAwareChannelResolver(this.binder, null);
|
||||
this.resolver.setBeanFactory(context);
|
||||
context.getBeanFactory().registerSingleton("channelResolver",
|
||||
this.resolver);
|
||||
@@ -79,7 +79,7 @@ public class MessageBusAwareChannelResolverTests {
|
||||
|
||||
PollerMetadata poller = new PollerMetadata();
|
||||
poller.setTrigger(new PeriodicTrigger(1000));
|
||||
bus.setPoller(poller);
|
||||
binder.setPoller(poller);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -96,7 +96,7 @@ public class MessageBusAwareChannelResolverTests {
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
bus.bindConsumer("queue:foo", testChannel, null);
|
||||
binder.bindConsumer("queue:foo", testChannel, null);
|
||||
assertEquals(0, received.size());
|
||||
registered.send(MessageBuilder.withPayload("hello").build());
|
||||
try {
|
||||
@@ -128,7 +128,7 @@ public class MessageBusAwareChannelResolverTests {
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
bus.bindPubSubConsumer("topic:bar", testChannel, null);
|
||||
binder.bindPubSubConsumer("topic:bar", testChannel, null);
|
||||
}
|
||||
assertEquals(0, received.size());
|
||||
registered.send(MessageBuilder.withPayload("hello").build());
|
||||
@@ -155,16 +155,16 @@ public class MessageBusAwareChannelResolverTests {
|
||||
@Test
|
||||
public void propertyPassthrough() {
|
||||
Properties properties = new Properties();
|
||||
MessageBus bus = mock(MessageBus.class);
|
||||
doReturn(new DirectChannel()).when(bus).bindDynamicProducer("queue:foo", properties);
|
||||
doReturn(new DirectChannel()).when(bus).bindDynamicPubSubProducer("topic:bar", properties);
|
||||
MessageBusAwareChannelResolver resolver = new MessageBusAwareChannelResolver(bus, properties);
|
||||
Binder binder = mock(Binder.class);
|
||||
doReturn(new DirectChannel()).when(binder).bindDynamicProducer("queue:foo", properties);
|
||||
doReturn(new DirectChannel()).when(binder).bindDynamicPubSubProducer("topic:bar", properties);
|
||||
BinderAwareChannelResolver resolver = new BinderAwareChannelResolver(binder, properties);
|
||||
BeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
resolver.setBeanFactory(beanFactory);
|
||||
resolver.resolveDestination("queue:foo");
|
||||
resolver.resolveDestination("topic:bar");
|
||||
verify(bus).bindDynamicProducer("queue:foo", properties);
|
||||
verify(bus).bindDynamicPubSubProducer("topic:bar", properties);
|
||||
verify(binder).bindDynamicProducer("queue:foo", properties);
|
||||
verify(binder).bindDynamicPubSubProducer("topic:bar", properties);
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user