Add checkstyle support
Fixes #481 Execute checkstyle validation at build time. Add minimal set of rules. Ensure that existing code conforms to the rules.
This commit is contained in:
committed by
Ilayaperumal Gopinathan
parent
0bbabaf705
commit
147a0cb0bc
41
pom.xml
41
pom.xml
@@ -19,6 +19,7 @@
|
||||
</scm>
|
||||
<properties>
|
||||
<java.version>1.7</java.version>
|
||||
<disable.checks>false</disable.checks>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
@@ -46,6 +47,21 @@
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>2.17</version>
|
||||
<configuration>
|
||||
<configLocation>src/checkstyle/checkstyle.xml</configLocation>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.puppycrawl.tools</groupId>
|
||||
<artifactId>checkstyle</artifactId>
|
||||
<version>6.17</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
@@ -62,6 +78,31 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>checkstyle-validation</id>
|
||||
<phase>validate</phase>
|
||||
<configuration>
|
||||
<skip>${disable.checks}</skip>
|
||||
<configLocation>src/checkstyle/checkstyle.xml</configLocation>
|
||||
<headerLocation>src/checkstyle/checkstyle-header.txt</headerLocation>
|
||||
<propertyExpansion>checkstyle.build.directory=${project.build.directory}</propertyExpansion>
|
||||
<encoding>UTF-8</encoding>
|
||||
<consoleOutput>true</consoleOutput>
|
||||
<failsOnError>true</failsOnError>
|
||||
<includeTestSourceDirectory>true</includeTestSourceDirectory>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<profiles>
|
||||
<profile>
|
||||
|
||||
@@ -18,8 +18,6 @@ package org.springframework.cloud.stream.binder.kafka;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
|
||||
import org.springframework.cloud.stream.binder.ConsumerProperties;
|
||||
|
||||
/**
|
||||
* @author Marius Bogoevici
|
||||
*/
|
||||
|
||||
@@ -29,6 +29,12 @@ import java.util.Properties;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import kafka.admin.AdminUtils;
|
||||
import kafka.api.OffsetRequest;
|
||||
import kafka.serializer.Decoder;
|
||||
import kafka.serializer.DefaultDecoder;
|
||||
import kafka.utils.ZKStringSerializer$;
|
||||
import kafka.utils.ZkUtils;
|
||||
import org.I0Itec.zkclient.ZkClient;
|
||||
import org.apache.kafka.clients.producer.ProducerConfig;
|
||||
import org.apache.kafka.common.serialization.ByteArraySerializer;
|
||||
@@ -83,12 +89,6 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import kafka.admin.AdminUtils;
|
||||
import kafka.api.OffsetRequest;
|
||||
import kafka.serializer.Decoder;
|
||||
import kafka.serializer.DefaultDecoder;
|
||||
import kafka.utils.ZKStringSerializer$;
|
||||
import kafka.utils.ZkUtils;
|
||||
import scala.collection.Seq;
|
||||
|
||||
/**
|
||||
@@ -150,17 +150,17 @@ public class KafkaMessageChannelBinder extends AbstractBinder<MessageChannel, Ex
|
||||
|
||||
private KafkaExtendedBindingProperties extendedBindingProperties = new KafkaExtendedBindingProperties();
|
||||
|
||||
public KafkaMessageChannelBinder(ZookeeperConnect zookeeperConnect, String brokers, String zkAddress,
|
||||
String... headersToMap) {
|
||||
public KafkaMessageChannelBinder(ZookeeperConnect zookeeperConnect, String brokers,
|
||||
String zkAddress, String... headersToMap) {
|
||||
this.zookeeperConnect = zookeeperConnect;
|
||||
this.brokers = brokers;
|
||||
this.zkAddress = zkAddress;
|
||||
if (headersToMap.length > 0) {
|
||||
String[] combinedHeadersToMap =
|
||||
Arrays.copyOfRange(BinderHeaders.STANDARD_HEADERS, 0, BinderHeaders.STANDARD_HEADERS.length + headersToMap
|
||||
.length);
|
||||
System.arraycopy(headersToMap, 0, combinedHeadersToMap, BinderHeaders.STANDARD_HEADERS.length, headersToMap
|
||||
.length);
|
||||
String[] combinedHeadersToMap = Arrays.copyOfRange(
|
||||
BinderHeaders.STANDARD_HEADERS, 0,
|
||||
BinderHeaders.STANDARD_HEADERS.length + headersToMap.length);
|
||||
System.arraycopy(headersToMap, 0, combinedHeadersToMap,
|
||||
BinderHeaders.STANDARD_HEADERS.length, headersToMap.length);
|
||||
this.headersToMap = combinedHeadersToMap;
|
||||
}
|
||||
else {
|
||||
@@ -502,8 +502,8 @@ public class KafkaMessageChannelBinder extends AbstractBinder<MessageChannel, Ex
|
||||
|
||||
KafkaMessageListenerContainer createMessageListenerContainer(
|
||||
ExtendedConsumerProperties<KafkaConsumerProperties> consumerProperties,
|
||||
String group, String topic, Collection<Partition> listenedPartitions,
|
||||
long referencePoint) {
|
||||
String group, String topic, Collection<Partition> listenedPartitions,
|
||||
long referencePoint) {
|
||||
Assert.isTrue(StringUtils.hasText(topic) ^ !CollectionUtils.isEmpty(listenedPartitions),
|
||||
"Exactly one of topic or a list of listened partitions must be provided");
|
||||
KafkaMessageListenerContainer messageListenerContainer;
|
||||
@@ -617,7 +617,7 @@ public class KafkaMessageChannelBinder extends AbstractBinder<MessageChannel, Ex
|
||||
|
||||
private SendingHandler(String topicName, ExtendedProducerProperties<KafkaProducerProperties> properties,
|
||||
int numberOfPartitions,
|
||||
ProducerConfiguration<byte[], byte[]> producerConfiguration) {
|
||||
ProducerConfiguration<byte[], byte[]> producerConfiguration) {
|
||||
this.topicName = topicName;
|
||||
producerProperties = properties;
|
||||
this.numberOfKafkaPartitions = numberOfPartitions;
|
||||
|
||||
@@ -23,9 +23,6 @@ import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
|
||||
import com.rabbitmq.client.AMQP;
|
||||
import com.rabbitmq.client.Channel;
|
||||
import com.rabbitmq.client.Envelope;
|
||||
import org.aopalliance.aop.Advice;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -91,6 +88,10 @@ import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.rabbitmq.client.AMQP;
|
||||
import com.rabbitmq.client.Channel;
|
||||
import com.rabbitmq.client.Envelope;
|
||||
|
||||
/**
|
||||
* A {@link org.springframework.cloud.stream.binder.Binder} implementation backed by RabbitMQ.
|
||||
*
|
||||
@@ -354,7 +355,7 @@ public class RabbitMessageChannelBinder extends AbstractBinder<MessageChannel, E
|
||||
|
||||
private AmqpOutboundEndpoint buildOutboundEndpoint(final String name,
|
||||
ExtendedProducerProperties<RabbitProducerProperties> properties,
|
||||
RabbitTemplate rabbitTemplate) {
|
||||
RabbitTemplate rabbitTemplate) {
|
||||
String prefix = properties.getExtension().getPrefix();
|
||||
String exchangeName = applyPrefix(prefix, name);
|
||||
TopicExchange exchange = new TopicExchange(exchangeName);
|
||||
|
||||
@@ -24,38 +24,41 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class TestUtils {
|
||||
|
||||
/**
|
||||
* Uses nested {@link DirectFieldAccessor}s to obtain a property using dotted notation to traverse fields; e.g.
|
||||
* "foo.bar.baz" will obtain a reference to the baz field of the bar field of foo. Adopted from Spring Integration.
|
||||
* @param root The object.
|
||||
* @param propertyPath The path.
|
||||
* @return The field.
|
||||
*/
|
||||
public static Object getPropertyValue(Object root, String propertyPath) {
|
||||
Object value = null;
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(root);
|
||||
String[] tokens = propertyPath.split("\\.");
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
value = accessor.getPropertyValue(tokens[i]);
|
||||
if (value != null) {
|
||||
accessor = new DirectFieldAccessor(value);
|
||||
}
|
||||
else if (i == tokens.length - 1) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("intermediate property '" + tokens[i] + "' is null");
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
/**
|
||||
* Uses nested {@link DirectFieldAccessor}s to obtain a property using dotted notation
|
||||
* to traverse fields; e.g. "foo.bar.baz" will obtain a reference to the baz field of
|
||||
* the bar field of foo. Adopted from Spring Integration.
|
||||
* @param root The object.
|
||||
* @param propertyPath The path.
|
||||
* @return The field.
|
||||
*/
|
||||
public static Object getPropertyValue(Object root, String propertyPath) {
|
||||
Object value = null;
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(root);
|
||||
String[] tokens = propertyPath.split("\\.");
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
value = accessor.getPropertyValue(tokens[i]);
|
||||
if (value != null) {
|
||||
accessor = new DirectFieldAccessor(value);
|
||||
}
|
||||
else if (i == tokens.length - 1) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(
|
||||
"intermediate property '" + tokens[i] + "' is null");
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T getPropertyValue(Object root, String propertyPath, Class<T> type) {
|
||||
Object value = getPropertyValue(root, propertyPath);
|
||||
if (value != null) {
|
||||
Assert.isAssignable(type, value.getClass());
|
||||
}
|
||||
return (T) value;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T getPropertyValue(Object root, String propertyPath,
|
||||
Class<T> type) {
|
||||
Object value = getPropertyValue(root, propertyPath);
|
||||
if (value != null) {
|
||||
Assert.isAssignable(type, value.getClass());
|
||||
}
|
||||
return (T) value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,48 +68,64 @@ public class StreamListenerTests {
|
||||
Sink sink = context.getBean(Sink.class);
|
||||
String id = UUID.randomUUID().toString();
|
||||
sink.input().send(MessageBuilder.withPayload("{\"bar\":\"barbar" + id + "\"}")
|
||||
.setHeader("contentType", "application/json").build());
|
||||
.setHeader("contentType", "application/json").build());
|
||||
assertTrue(testSink.latch.await(10, TimeUnit.SECONDS));
|
||||
assertThat(testSink.receivedArguments, hasSize(1));
|
||||
assertThat(testSink.receivedArguments.get(0), hasProperty("bar", equalTo("barbar" + id)));
|
||||
assertThat(testSink.receivedArguments.get(0),
|
||||
hasProperty("bar", equalTo("barbar" + id)));
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testAnnotatedArguments() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestPojoWithAnnotatedArguments.class);
|
||||
ConfigurableApplicationContext context = SpringApplication
|
||||
.run(TestPojoWithAnnotatedArguments.class);
|
||||
|
||||
TestPojoWithAnnotatedArguments testPojoWithAnnotatedArguments = context.getBean(TestPojoWithAnnotatedArguments.class);
|
||||
TestPojoWithAnnotatedArguments testPojoWithAnnotatedArguments = context
|
||||
.getBean(TestPojoWithAnnotatedArguments.class);
|
||||
Sink sink = context.getBean(Sink.class);
|
||||
String id = UUID.randomUUID().toString();
|
||||
sink.input().send(MessageBuilder.withPayload("{\"bar\":\"barbar" + id + "\"}")
|
||||
.setHeader("contentType", "application/json").setHeader("testHeader", "testValue").build());
|
||||
sink.input()
|
||||
.send(MessageBuilder.withPayload("{\"bar\":\"barbar" + id + "\"}")
|
||||
.setHeader("contentType", "application/json")
|
||||
.setHeader("testHeader", "testValue").build());
|
||||
assertThat(testPojoWithAnnotatedArguments.receivedArguments, hasSize(3));
|
||||
assertThat(testPojoWithAnnotatedArguments.receivedArguments.get(0), instanceOf(FooPojo.class));
|
||||
assertThat(testPojoWithAnnotatedArguments.receivedArguments.get(0), hasProperty("bar", equalTo("barbar" + id)));
|
||||
assertThat(testPojoWithAnnotatedArguments.receivedArguments.get(1), instanceOf(Map.class));
|
||||
assertThat((Map<String, String>) testPojoWithAnnotatedArguments.receivedArguments.get(1),
|
||||
assertThat(testPojoWithAnnotatedArguments.receivedArguments.get(0),
|
||||
instanceOf(FooPojo.class));
|
||||
assertThat(testPojoWithAnnotatedArguments.receivedArguments.get(0),
|
||||
hasProperty("bar", equalTo("barbar" + id)));
|
||||
assertThat(testPojoWithAnnotatedArguments.receivedArguments.get(1),
|
||||
instanceOf(Map.class));
|
||||
assertThat(
|
||||
(Map<String, String>) testPojoWithAnnotatedArguments.receivedArguments
|
||||
.get(1),
|
||||
hasEntry(MessageHeaders.CONTENT_TYPE, "application/json"));
|
||||
assertThat((Map<String, String>) testPojoWithAnnotatedArguments.receivedArguments.get(1),
|
||||
hasEntry(equalTo("testHeader"), equalTo("testValue")));
|
||||
assertThat((String) testPojoWithAnnotatedArguments.receivedArguments.get(2), equalTo("application/json"));
|
||||
assertThat((Map<String, String>) testPojoWithAnnotatedArguments.receivedArguments
|
||||
.get(1), hasEntry(equalTo("testHeader"), equalTo("testValue")));
|
||||
assertThat((String) testPojoWithAnnotatedArguments.receivedArguments.get(2),
|
||||
equalTo("application/json"));
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testReturn() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestStringProcessor.class);
|
||||
ConfigurableApplicationContext context = SpringApplication
|
||||
.run(TestStringProcessor.class);
|
||||
MessageCollector collector = context.getBean(MessageCollector.class);
|
||||
Processor processor = context.getBean(Processor.class);
|
||||
String id = UUID.randomUUID().toString();
|
||||
processor.input().send(MessageBuilder.withPayload("{\"bar\":\"barbar" + id + "\"}")
|
||||
.setHeader("contentType", "application/json").build());
|
||||
Message<String> message = (Message<String>) collector.forChannel(processor.output()).poll(1, TimeUnit.SECONDS);
|
||||
TestStringProcessor testStringProcessor = context.getBean(TestStringProcessor.class);
|
||||
processor.input()
|
||||
.send(MessageBuilder.withPayload("{\"bar\":\"barbar" + id + "\"}")
|
||||
.setHeader("contentType", "application/json").build());
|
||||
Message<String> message = (Message<String>) collector
|
||||
.forChannel(processor.output()).poll(1, TimeUnit.SECONDS);
|
||||
TestStringProcessor testStringProcessor = context
|
||||
.getBean(TestStringProcessor.class);
|
||||
assertThat(testStringProcessor.receivedPojos, hasSize(1));
|
||||
assertThat(testStringProcessor.receivedPojos.get(0), hasProperty("bar", equalTo("barbar" + id)));
|
||||
assertThat(testStringProcessor.receivedPojos.get(0),
|
||||
hasProperty("bar", equalTo("barbar" + id)));
|
||||
assertThat(message, not(nullValue(Message.class)));
|
||||
assertThat(message.getPayload(), equalTo("barbar" + id));
|
||||
context.close();
|
||||
@@ -118,36 +134,47 @@ public class StreamListenerTests {
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testReturnConversion() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestPojoWithMimeType.class,
|
||||
ConfigurableApplicationContext context = SpringApplication.run(
|
||||
TestPojoWithMimeType.class,
|
||||
"--spring.cloud.stream.bindings.output.contentType=application/json");
|
||||
MessageCollector collector = context.getBean(MessageCollector.class);
|
||||
Processor processor = context.getBean(Processor.class);
|
||||
String id = UUID.randomUUID().toString();
|
||||
processor.input().send(MessageBuilder.withPayload("{\"bar\":\"barbar" + id + "\"}")
|
||||
.setHeader("contentType", "application/json").build());
|
||||
TestPojoWithMimeType testPojoWithMimeType = context.getBean(TestPojoWithMimeType.class);
|
||||
processor.input()
|
||||
.send(MessageBuilder.withPayload("{\"bar\":\"barbar" + id + "\"}")
|
||||
.setHeader("contentType", "application/json").build());
|
||||
TestPojoWithMimeType testPojoWithMimeType = context
|
||||
.getBean(TestPojoWithMimeType.class);
|
||||
assertThat(testPojoWithMimeType.receivedPojos, hasSize(1));
|
||||
assertThat(testPojoWithMimeType.receivedPojos.get(0), hasProperty("bar", equalTo("barbar" + id)));
|
||||
Message<String> message = (Message<String>) collector.forChannel(processor.output()).poll(1, TimeUnit.SECONDS);
|
||||
assertThat(testPojoWithMimeType.receivedPojos.get(0),
|
||||
hasProperty("bar", equalTo("barbar" + id)));
|
||||
Message<String> message = (Message<String>) collector
|
||||
.forChannel(processor.output()).poll(1, TimeUnit.SECONDS);
|
||||
assertThat(message, not(nullValue(Message.class)));
|
||||
assertThat(message.getPayload(), equalTo("{\"qux\":\"barbar" + id + "\"}"));
|
||||
assertThat(message.getHeaders().get(MessageHeaders.CONTENT_TYPE, String.class), equalTo("application/json"));
|
||||
assertThat(message.getHeaders().get(MessageHeaders.CONTENT_TYPE, String.class),
|
||||
equalTo("application/json"));
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testReturnNoConversion() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestPojoWithMimeType.class);
|
||||
ConfigurableApplicationContext context = SpringApplication
|
||||
.run(TestPojoWithMimeType.class);
|
||||
MessageCollector collector = context.getBean(MessageCollector.class);
|
||||
Processor processor = context.getBean(Processor.class);
|
||||
String id = UUID.randomUUID().toString();
|
||||
processor.input().send(MessageBuilder.withPayload("{\"bar\":\"barbar" + id + "\"}")
|
||||
.setHeader("contentType", "application/json").build());
|
||||
TestPojoWithMimeType testPojoWithMimeType = context.getBean(TestPojoWithMimeType.class);
|
||||
processor.input()
|
||||
.send(MessageBuilder.withPayload("{\"bar\":\"barbar" + id + "\"}")
|
||||
.setHeader("contentType", "application/json").build());
|
||||
TestPojoWithMimeType testPojoWithMimeType = context
|
||||
.getBean(TestPojoWithMimeType.class);
|
||||
assertThat(testPojoWithMimeType.receivedPojos, hasSize(1));
|
||||
assertThat(testPojoWithMimeType.receivedPojos.get(0), hasProperty("bar", equalTo("barbar" + id)));
|
||||
Message<BazPojo> message = (Message<BazPojo>) collector.forChannel(processor.output()).poll(1, TimeUnit.SECONDS);
|
||||
assertThat(testPojoWithMimeType.receivedPojos.get(0),
|
||||
hasProperty("bar", equalTo("barbar" + id)));
|
||||
Message<BazPojo> message = (Message<BazPojo>) collector
|
||||
.forChannel(processor.output()).poll(1, TimeUnit.SECONDS);
|
||||
assertThat(message, not(nullValue(Message.class)));
|
||||
assertThat(message.getPayload().getQux(), equalTo("barbar" + id));
|
||||
context.close();
|
||||
@@ -156,16 +183,21 @@ public class StreamListenerTests {
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testReturnMessage() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestPojoWithMessageReturn.class);
|
||||
ConfigurableApplicationContext context = SpringApplication
|
||||
.run(TestPojoWithMessageReturn.class);
|
||||
MessageCollector collector = context.getBean(MessageCollector.class);
|
||||
Processor processor = context.getBean(Processor.class);
|
||||
String id = UUID.randomUUID().toString();
|
||||
processor.input().send(MessageBuilder.withPayload("{\"bar\":\"barbar" + id + "\"}")
|
||||
.setHeader("contentType", "application/json").build());
|
||||
TestPojoWithMessageReturn testPojoWithMessageReturn = context.getBean(TestPojoWithMessageReturn.class);
|
||||
processor.input()
|
||||
.send(MessageBuilder.withPayload("{\"bar\":\"barbar" + id + "\"}")
|
||||
.setHeader("contentType", "application/json").build());
|
||||
TestPojoWithMessageReturn testPojoWithMessageReturn = context
|
||||
.getBean(TestPojoWithMessageReturn.class);
|
||||
assertThat(testPojoWithMessageReturn.receivedPojos, hasSize(1));
|
||||
assertThat(testPojoWithMessageReturn.receivedPojos.get(0), hasProperty("bar", equalTo("barbar" + id)));
|
||||
Message<BazPojo> message = (Message<BazPojo>) collector.forChannel(processor.output()).poll(1, TimeUnit.SECONDS);
|
||||
assertThat(testPojoWithMessageReturn.receivedPojos.get(0),
|
||||
hasProperty("bar", equalTo("barbar" + id)));
|
||||
Message<BazPojo> message = (Message<BazPojo>) collector
|
||||
.forChannel(processor.output()).poll(1, TimeUnit.SECONDS);
|
||||
assertThat(message, not(nullValue(Message.class)));
|
||||
assertThat(message.getPayload().getQux(), equalTo("barbar" + id));
|
||||
context.close();
|
||||
@@ -174,16 +206,20 @@ public class StreamListenerTests {
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testMessageArgument() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestPojoWithMessageArgument.class);
|
||||
ConfigurableApplicationContext context = SpringApplication
|
||||
.run(TestPojoWithMessageArgument.class);
|
||||
MessageCollector collector = context.getBean(MessageCollector.class);
|
||||
Processor processor = context.getBean(Processor.class);
|
||||
String id = UUID.randomUUID().toString();
|
||||
processor.input().send(MessageBuilder.withPayload("barbar" + id)
|
||||
.setHeader("contentType", "text/plain").build());
|
||||
TestPojoWithMessageArgument testPojoWithMessageArgument = context.getBean(TestPojoWithMessageArgument.class);
|
||||
.setHeader("contentType", "text/plain").build());
|
||||
TestPojoWithMessageArgument testPojoWithMessageArgument = context
|
||||
.getBean(TestPojoWithMessageArgument.class);
|
||||
assertThat(testPojoWithMessageArgument.receivedMessages, hasSize(1));
|
||||
assertThat(testPojoWithMessageArgument.receivedMessages.get(0).getPayload(), equalTo("barbar" + id));
|
||||
Message<BazPojo> message = (Message<BazPojo>) collector.forChannel(processor.output()).poll(1, TimeUnit.SECONDS);
|
||||
assertThat(testPojoWithMessageArgument.receivedMessages.get(0).getPayload(),
|
||||
equalTo("barbar" + id));
|
||||
Message<BazPojo> message = (Message<BazPojo>) collector
|
||||
.forChannel(processor.output()).poll(1, TimeUnit.SECONDS);
|
||||
assertThat(message, not(nullValue(Message.class)));
|
||||
assertThat(message.getPayload().getQux(), equalTo("barbar" + id));
|
||||
context.close();
|
||||
@@ -193,32 +229,38 @@ public class StreamListenerTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testDuplicateMapping() throws Exception {
|
||||
try {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestDuplicateMapping.class);
|
||||
ConfigurableApplicationContext context = SpringApplication
|
||||
.run(TestDuplicateMapping.class);
|
||||
fail("Exception expected on duplicate mapping");
|
||||
}
|
||||
catch (BeanCreationException e) {
|
||||
assertThat(e.getCause().getMessage(), startsWith("Duplicate @StreamListener mapping"));
|
||||
assertThat(e.getCause().getMessage(),
|
||||
startsWith("Duplicate @StreamListener mapping"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testHandlerBean() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestHandlerBean.class,
|
||||
ConfigurableApplicationContext context = SpringApplication.run(
|
||||
TestHandlerBean.class,
|
||||
"--spring.cloud.stream.bindings.output.contentType=application/json");
|
||||
MessageCollector collector = context.getBean(MessageCollector.class);
|
||||
Processor processor = context.getBean(Processor.class);
|
||||
String id = UUID.randomUUID().toString();
|
||||
processor.input().send(MessageBuilder.withPayload("{\"bar\":\"barbar" + id + "\"}")
|
||||
.setHeader("contentType", "application/json").build());
|
||||
processor.input()
|
||||
.send(MessageBuilder.withPayload("{\"bar\":\"barbar" + id + "\"}")
|
||||
.setHeader("contentType", "application/json").build());
|
||||
HandlerBean handlerBean = context.getBean(HandlerBean.class);
|
||||
assertThat(handlerBean.receivedPojos, hasSize(1));
|
||||
assertThat(handlerBean.receivedPojos.get(0), hasProperty("bar", equalTo("barbar" + id)));
|
||||
Message<String> message = (Message<String>) collector.forChannel(processor.output()).poll(1, TimeUnit.SECONDS);
|
||||
assertThat(handlerBean.receivedPojos.get(0),
|
||||
hasProperty("bar", equalTo("barbar" + id)));
|
||||
Message<String> message = (Message<String>) collector
|
||||
.forChannel(processor.output()).poll(1, TimeUnit.SECONDS);
|
||||
assertThat(message, not(nullValue(Message.class)));
|
||||
assertThat(message.getPayload(), equalTo("{\"qux\":\"barbar" + id + "\"}"));
|
||||
assertThat(message.getHeaders().get(MessageHeaders.CONTENT_TYPE, String.class), equalTo("application/json"));
|
||||
assertThat(message.getHeaders().get(MessageHeaders.CONTENT_TYPE, String.class),
|
||||
equalTo("application/json"));
|
||||
context.close();
|
||||
}
|
||||
|
||||
@@ -230,7 +272,6 @@ public class StreamListenerTests {
|
||||
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
|
||||
@StreamListener(Sink.INPUT)
|
||||
public void receive(FooPojo fooPojo) {
|
||||
receivedArguments.add(fooPojo);
|
||||
@@ -275,8 +316,9 @@ public class StreamListenerTests {
|
||||
List<Object> receivedArguments = new ArrayList<>();
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public void receive(@Payload FooPojo fooPojo, @Headers Map<String, Object> headers,
|
||||
@Header(MessageHeaders.CONTENT_TYPE) String contentType) {
|
||||
public void receive(@Payload FooPojo fooPojo,
|
||||
@Headers Map<String, Object> headers,
|
||||
@Header(MessageHeaders.CONTENT_TYPE) String contentType) {
|
||||
receivedArguments.add(fooPojo);
|
||||
receivedArguments.add(headers);
|
||||
receivedArguments.add(contentType);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,105 +29,110 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Abstract base class for JUnit {@link Rule}s that detect the presence of some external resource. If the resource is
|
||||
* indeed present, it will be available during the test lifecycle through {@link #getResource()}. If it is not, tests
|
||||
* will either fail or be skipped, depending on the value of system property {@value #SCS_EXTERNAL_SERVERS_REQUIRED}.
|
||||
* Abstract base class for JUnit {@link Rule}s that detect the presence of some external
|
||||
* resource. If the resource is indeed present, it will be available during the test
|
||||
* lifecycle through {@link #getResource()}. If it is not, tests will either fail or be
|
||||
* skipped, depending on the value of system property
|
||||
* {@value #SCS_EXTERNAL_SERVERS_REQUIRED}.
|
||||
*
|
||||
* @author Eric Bottard
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public abstract class AbstractExternalResourceTestSupport<R> implements TestRule {
|
||||
|
||||
public static final String SCS_EXTERNAL_SERVERS_REQUIRED = "SCS_EXTERNAL_SERVERS_REQUIRED";
|
||||
public static final String SCS_EXTERNAL_SERVERS_REQUIRED = "SCS_EXTERNAL_SERVERS_REQUIRED";
|
||||
|
||||
protected R resource;
|
||||
protected R resource;
|
||||
|
||||
private String resourceDescription;
|
||||
private String resourceDescription;
|
||||
|
||||
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
protected AbstractExternalResourceTestSupport(String resourceDescription) {
|
||||
Assert.hasText(resourceDescription, "resourceDescription is required");
|
||||
this.resourceDescription = resourceDescription;
|
||||
}
|
||||
protected AbstractExternalResourceTestSupport(String resourceDescription) {
|
||||
Assert.hasText(resourceDescription, "resourceDescription is required");
|
||||
this.resourceDescription = resourceDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Statement apply(final Statement base, Description description) {
|
||||
try {
|
||||
obtainResource();
|
||||
}
|
||||
catch (Exception e) {
|
||||
maybeCleanup();
|
||||
@Override
|
||||
public Statement apply(final Statement base, Description description) {
|
||||
try {
|
||||
obtainResource();
|
||||
}
|
||||
catch (Exception e) {
|
||||
maybeCleanup();
|
||||
|
||||
return failOrSkip(e);
|
||||
}
|
||||
return failOrSkip(e);
|
||||
}
|
||||
|
||||
return new Statement() {
|
||||
return new Statement() {
|
||||
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
try {
|
||||
base.evaluate();
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
cleanupResource();
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
logger.warn("Exception while trying to cleanup proper resource", ignored);
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
try {
|
||||
base.evaluate();
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
cleanupResource();
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
logger.warn("Exception while trying to cleanup proper resource",
|
||||
ignored);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Statement failOrSkip(final Exception e) {
|
||||
String serversRequired = System.getenv(SCS_EXTERNAL_SERVERS_REQUIRED);
|
||||
if ("true".equalsIgnoreCase(serversRequired)) {
|
||||
logger.error(resourceDescription + " IS REQUIRED BUT NOT AVAILABLE", e);
|
||||
fail(resourceDescription + " IS NOT AVAILABLE");
|
||||
// Never reached, here to satisfy method signature
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
logger.error(resourceDescription + " IS NOT AVAILABLE, SKIPPING TESTS", e);
|
||||
return new Statement() {
|
||||
private Statement failOrSkip(final Exception e) {
|
||||
String serversRequired = System.getenv(SCS_EXTERNAL_SERVERS_REQUIRED);
|
||||
if ("true".equalsIgnoreCase(serversRequired)) {
|
||||
logger.error(resourceDescription + " IS REQUIRED BUT NOT AVAILABLE", e);
|
||||
fail(resourceDescription + " IS NOT AVAILABLE");
|
||||
// Never reached, here to satisfy method signature
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
logger.error(resourceDescription + " IS NOT AVAILABLE, SKIPPING TESTS", e);
|
||||
return new Statement() {
|
||||
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
Assume.assumeTrue("Skipping test due to " + resourceDescription + " not being available " + e, false);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
Assume.assumeTrue("Skipping test due to " + resourceDescription
|
||||
+ " not being available " + e, false);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void maybeCleanup() {
|
||||
if (resource != null) {
|
||||
try {
|
||||
cleanupResource();
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
logger.warn("Exception while trying to cleanup failed resource", ignored);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void maybeCleanup() {
|
||||
if (resource != null) {
|
||||
try {
|
||||
cleanupResource();
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
logger.warn("Exception while trying to cleanup failed resource", ignored);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public R getResource() {
|
||||
return resource;
|
||||
}
|
||||
public R getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform cleanup of the {@link #resource} field, which is guaranteed to be non null.
|
||||
*
|
||||
* @throws Exception any exception thrown by this method will be logged and swallowed
|
||||
*/
|
||||
protected abstract void cleanupResource() throws Exception;
|
||||
/**
|
||||
* Perform cleanup of the {@link #resource} field, which is guaranteed to be non null.
|
||||
*
|
||||
* @throws Exception any exception thrown by this method will be logged and swallowed
|
||||
*/
|
||||
protected abstract void cleanupResource() throws Exception;
|
||||
|
||||
/**
|
||||
* Try to obtain and validate a resource. Implementors should either set the {@link #resource} field with a valid
|
||||
* resource and return normally, or throw an exception.
|
||||
*/
|
||||
protected abstract void obtainResource() throws Exception;
|
||||
/**
|
||||
* Try to obtain and validate a resource. Implementors should either set the
|
||||
* {@link #resource} field with a valid resource and return normally, or throw an
|
||||
* exception.
|
||||
*/
|
||||
protected abstract void obtainResource() throws Exception;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,30 +16,15 @@
|
||||
|
||||
package org.springframework.cloud.stream.test.junit.kafka;
|
||||
|
||||
import kafka.admin.AdminUtils;
|
||||
import kafka.consumer.Consumer;
|
||||
import kafka.consumer.ConsumerConfig;
|
||||
import kafka.javaapi.consumer.ConsumerConnector;
|
||||
import kafka.server.KafkaConfig;
|
||||
import kafka.server.KafkaServerStartable;
|
||||
|
||||
import kafka.utils.TestUtils;
|
||||
import org.I0Itec.zkclient.ZkClient;
|
||||
import org.apache.curator.framework.CuratorFramework;
|
||||
import org.apache.curator.framework.CuratorFrameworkFactory;
|
||||
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
|
||||
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
|
||||
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
|
||||
import org.apache.curator.retry.RetryUntilElapsed;
|
||||
import org.apache.curator.test.TestingServer;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.SocketUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Properties;
|
||||
|
||||
import kafka.server.KafkaConfig;
|
||||
import kafka.server.KafkaServerStartable;
|
||||
import kafka.utils.TestUtils;
|
||||
import org.apache.curator.test.TestingServer;
|
||||
|
||||
import org.springframework.util.SocketUtils;
|
||||
|
||||
/**
|
||||
* A test Kafka + ZooKeeper pair for testing purposes.
|
||||
@@ -65,8 +50,8 @@ public class TestKafkaCluster {
|
||||
}
|
||||
|
||||
private static KafkaConfig getKafkaConfig(final String zkConnectString) {
|
||||
scala.collection.Iterator<Properties> propsI =
|
||||
TestUtils.createBrokerConfigs(1, false).iterator();
|
||||
scala.collection.Iterator<Properties> propsI = TestUtils
|
||||
.createBrokerConfigs(1, false).iterator();
|
||||
assert propsI.hasNext();
|
||||
Properties props = propsI.next();
|
||||
assert props.containsKey("zookeeper.connect");
|
||||
@@ -75,8 +60,7 @@ public class TestKafkaCluster {
|
||||
}
|
||||
|
||||
public String getKafkaBrokerString() {
|
||||
return String.format("localhost:%d",
|
||||
kafkaServer.serverConfig().port());
|
||||
return String.format("localhost:%d", kafkaServer.serverConfig().port());
|
||||
}
|
||||
|
||||
public void stop() throws IOException {
|
||||
@@ -84,8 +68,6 @@ public class TestKafkaCluster {
|
||||
zkServer.stop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getZkConnectString() {
|
||||
return zkServer.getConnectString();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,7 +24,6 @@ import org.springframework.messaging.MessageChannel;
|
||||
|
||||
/**
|
||||
* A registry for channels that can be shared between modules, used for module aggregation.
|
||||
*
|
||||
* @author Marius Bogoevici
|
||||
*/
|
||||
public class SharedChannelRegistry {
|
||||
@@ -39,7 +38,7 @@ public class SharedChannelRegistry {
|
||||
}
|
||||
|
||||
public void register(String id, MessageChannel messageChannel) {
|
||||
sharedChannels.put(id, messageChannel);
|
||||
sharedChannels.put(id, messageChannel);
|
||||
}
|
||||
|
||||
public Map<String, MessageChannel> getAll() {
|
||||
|
||||
@@ -44,7 +44,6 @@ import org.springframework.validation.beanvalidation.CustomValidatorBean;
|
||||
/**
|
||||
* Handles the operations related to channel binding including binding of input/output channels by delegating
|
||||
* to an underlying {@link Binder}, setting up data type conversion for binding channel.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Dave Syer
|
||||
* @author Marius Bogoevici
|
||||
@@ -64,7 +63,7 @@ public class ChannelBindingService {
|
||||
private final Map<String, List<Binding<MessageChannel>>> consumerBindings = new HashMap<>();
|
||||
|
||||
public ChannelBindingService(ChannelBindingServiceProperties channelBindingServiceProperties,
|
||||
BinderFactory<MessageChannel> binderFactory) {
|
||||
BinderFactory<MessageChannel> binderFactory) {
|
||||
this.channelBindingServiceProperties = channelBindingServiceProperties;
|
||||
this.binderFactory = binderFactory;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.cloud.stream.binding;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -28,7 +27,6 @@ import org.springframework.context.SmartLifecycle;
|
||||
/**
|
||||
* Coordinates binding/unbinding of input channels in accordance to the lifecycle
|
||||
* of the host context.
|
||||
*
|
||||
* @author Marius Bogoevici
|
||||
* @author Ilayaperumal Gopinathan
|
||||
*/
|
||||
@@ -106,7 +104,8 @@ public class InputBindingLifecycle implements SmartLifecycle, ApplicationContext
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a high value so that this bean is started after receiving Lifecycle beans are started. Beans that need to start after bindings will set a higher phase value.
|
||||
* Return a high value so that this bean is started after receiving Lifecycle beans
|
||||
* are started. Beans that need to start after bindings will set a higher phase value.
|
||||
*/
|
||||
@Override
|
||||
public int getPhase() {
|
||||
|
||||
@@ -39,12 +39,10 @@ import org.springframework.util.MimeType;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
|
||||
* A {@link MessageChannelConfigurer} that sets data types and message converters based on {@link
|
||||
* BindingProperties#contentType}. Also adds a {@link org.springframework.messaging.support.ChannelInterceptor} to
|
||||
* the message channel to set the `ContentType` header for the message (if not already set) based on the `ContentType`
|
||||
* binding property of the channel.
|
||||
@
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @author Marius Bogoevici
|
||||
*/
|
||||
@@ -59,8 +57,8 @@ public class MessageConverterConfigurer implements MessageChannelConfigurer, Bea
|
||||
private final ChannelBindingServiceProperties channelBindingServiceProperties;
|
||||
|
||||
public MessageConverterConfigurer(ChannelBindingServiceProperties channelBindingServiceProperties,
|
||||
MessageBuilderFactory messageBuilderFactory,
|
||||
CompositeMessageConverterFactory compositeMessageConverterFactory) {
|
||||
MessageBuilderFactory messageBuilderFactory,
|
||||
CompositeMessageConverterFactory compositeMessageConverterFactory) {
|
||||
Assert.notNull(compositeMessageConverterFactory, "The message converter factory cannot be null");
|
||||
this.messageBuilderFactory = messageBuilderFactory;
|
||||
this.channelBindingServiceProperties = channelBindingServiceProperties;
|
||||
@@ -95,14 +93,15 @@ public class MessageConverterConfigurer implements MessageChannelConfigurer, Bea
|
||||
messageChannel.setDatatypes(supportedDataTypes);
|
||||
messageChannel.setMessageConverter(new MessageWrappingMessageConverter(messageConverter, mimeType));
|
||||
messageChannel.addInterceptor(new ChannelInterceptorAdapter() {
|
||||
|
||||
@Override
|
||||
public Message<?> preSend(Message<?> message, MessageChannel messageChannel) {
|
||||
Object contentTypeFromMessage = message.getHeaders().get(MessageHeaders.CONTENT_TYPE);
|
||||
if (contentTypeFromMessage == null) {
|
||||
return messageBuilderFactory
|
||||
.fromMessage(message)
|
||||
.setHeader(MessageHeaders.CONTENT_TYPE, contentType)
|
||||
.build();
|
||||
.fromMessage(message)
|
||||
.setHeader(MessageHeaders.CONTENT_TYPE, contentType)
|
||||
.build();
|
||||
}
|
||||
return message;
|
||||
}
|
||||
@@ -171,7 +170,9 @@ public class MessageConverterConfigurer implements MessageChannelConfigurer, Bea
|
||||
MimeType messageContentType = MessageConverterUtils.X_JAVA_OBJECT.equals(contentType) ?
|
||||
MessageConverterUtils.javaObjectMimeType(payload.getClass()) : contentType;
|
||||
return messageBuilderFactory.withPayload(payload).copyHeaders(headers)
|
||||
.copyHeaders(Collections.singletonMap(MessageHeaders.CONTENT_TYPE, messageContentType.toString())).build();
|
||||
.copyHeaders(Collections.singletonMap(MessageHeaders.CONTENT_TYPE,
|
||||
messageContentType.toString()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public class BinderFactoryConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(BinderFactory.class)
|
||||
public BinderFactory binderFactory(BinderTypeRegistry binderTypeRegistry,
|
||||
ChannelBindingServiceProperties channelBindingServiceProperties) {
|
||||
ChannelBindingServiceProperties channelBindingServiceProperties) {
|
||||
Map<String, BinderConfiguration> binderConfigurations = new HashMap<>();
|
||||
if (!CollectionUtils.isEmpty(channelBindingServiceProperties.getBinders())) {
|
||||
for (Map.Entry<String, BinderProperties> binderEntry :
|
||||
@@ -120,8 +120,8 @@ public class BinderFactoryConfiguration {
|
||||
Collection<BinderType> parsedBinderConfigurations = new ArrayList<>();
|
||||
for (Map.Entry<?, ?> entry : properties.entrySet()) {
|
||||
String binderType = (String) entry.getKey();
|
||||
String[] binderConfigurationClassNames =
|
||||
StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
|
||||
String[] binderConfigurationClassNames = StringUtils
|
||||
.commaDelimitedListToStringArray((String) entry.getValue());
|
||||
Class[] binderConfigurationClasses = new Class[binderConfigurationClassNames.length];
|
||||
int i = 0;
|
||||
for (String binderConfigurationClassName : binderConfigurationClassNames) {
|
||||
|
||||
@@ -37,7 +37,6 @@ import org.springframework.util.MimeType;
|
||||
*
|
||||
* Extend this class to implement {@link org.springframework.messaging.converter.MessageConverter MessageConverters}
|
||||
* used with custom Message conversion. Only {@link #fromMessage} is supported.
|
||||
*
|
||||
* @author David Turanski
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @author Marius Bogoevici
|
||||
@@ -50,7 +49,6 @@ public abstract class AbstractFromMessageConverter extends AbstractMessageConver
|
||||
|
||||
/**
|
||||
* Creates a converter that ignores content-type message headers
|
||||
*
|
||||
* @param targetMimeType the required target type
|
||||
*/
|
||||
protected AbstractFromMessageConverter(MimeType targetMimeType) {
|
||||
@@ -63,7 +61,8 @@ public abstract class AbstractFromMessageConverter extends AbstractMessageConver
|
||||
|
||||
/**
|
||||
* Creates a converter that handles one or more content-type message headers
|
||||
* @param supportedSourceMimeTypes list of {@link MimeType} that may present in content-type header
|
||||
* @param supportedSourceMimeTypes list of {@link MimeType} that may present in
|
||||
* content-type header
|
||||
* @param targetMimeType the required target type
|
||||
*/
|
||||
protected AbstractFromMessageConverter(Collection<MimeType> supportedSourceMimeTypes, MimeType targetMimeType) {
|
||||
@@ -73,12 +72,13 @@ public abstract class AbstractFromMessageConverter extends AbstractMessageConver
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a converter that handles one or more content-type message headers and one or more target MIME types
|
||||
* @param supportedSourceMimeTypes a list of supported content types
|
||||
* Creates a converter that handles one or more content-type message headers and one
|
||||
* or more target MIME types
|
||||
* @param supportedSourceMimeTypes a list of supported content types
|
||||
* @param targetMimeTypes a list of supported target types
|
||||
*/
|
||||
protected AbstractFromMessageConverter(Collection<MimeType> supportedSourceMimeTypes,
|
||||
Collection<MimeType> targetMimeTypes) {
|
||||
Collection<MimeType> targetMimeTypes) {
|
||||
super(supportedSourceMimeTypes);
|
||||
Assert.notNull(targetMimeTypes, "'targetMimeTypes' cannot be null");
|
||||
this.targetMimeTypes = new ArrayList<>(targetMimeTypes);
|
||||
@@ -86,7 +86,8 @@ public abstract class AbstractFromMessageConverter extends AbstractMessageConver
|
||||
|
||||
/**
|
||||
* Creates a converter that requires a specific content-type message header
|
||||
* @param supportedSourceMimeType {@link MimeType} that must be present in content-type header
|
||||
* @param supportedSourceMimeType {@link MimeType} that must be present in
|
||||
* content-type header
|
||||
* @param targetMimeType the required target type
|
||||
*/
|
||||
protected AbstractFromMessageConverter(MimeType supportedSourceMimeType, MimeType targetMimeType) {
|
||||
@@ -94,8 +95,10 @@ public abstract class AbstractFromMessageConverter extends AbstractMessageConver
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a converter that requires a specific content-type message header and supports multiple target MIME types.
|
||||
* @param supportedSourceMimeType {@link MimeType} that must be present in content-type header
|
||||
* Creates a converter that requires a specific content-type message header and
|
||||
* supports multiple target MIME types.
|
||||
* @param supportedSourceMimeType {@link MimeType} that must be present in
|
||||
* content-type header
|
||||
* @param targetMimeTypes a list of supported target types
|
||||
*/
|
||||
protected AbstractFromMessageConverter(MimeType supportedSourceMimeType, Collection<MimeType> targetMimeTypes) {
|
||||
@@ -104,14 +107,12 @@ public abstract class AbstractFromMessageConverter extends AbstractMessageConver
|
||||
|
||||
/**
|
||||
* Subclasses implement this to specify supported target types
|
||||
*
|
||||
* @return an array of supported classes or null if any target type is supported
|
||||
*/
|
||||
protected abstract Class<?>[] supportedTargetTypes();
|
||||
|
||||
/**
|
||||
* Subclasses implement this to specify supported payload types
|
||||
*
|
||||
* @return an array of supported classes or null if any target type is supported
|
||||
*/
|
||||
protected abstract Class<?>[] supportedPayloadTypes();
|
||||
|
||||
@@ -21,8 +21,6 @@ import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
@@ -54,10 +52,14 @@ public class ArbitraryInterfaceBindingTestsWithDefaults {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testArbitraryInterfaceChannelsBound() {
|
||||
verify(binder).bindConsumer(eq("foo"), anyString(), eq(fooChannels.foo()), Mockito.<ConsumerProperties>any());
|
||||
verify(binder).bindConsumer(eq("bar"), anyString(), eq(fooChannels.bar()), Mockito.<ConsumerProperties>any());
|
||||
verify(binder).bindProducer(eq("baz"), eq(fooChannels.baz()), Mockito.<ProducerProperties>any());
|
||||
verify(binder).bindProducer(eq("qux"), eq(fooChannels.qux()), Mockito.<ProducerProperties>any());
|
||||
verify(binder).bindConsumer(eq("foo"), anyString(), eq(fooChannels.foo()),
|
||||
Mockito.<ConsumerProperties>any());
|
||||
verify(binder).bindConsumer(eq("bar"), anyString(), eq(fooChannels.bar()),
|
||||
Mockito.<ConsumerProperties>any());
|
||||
verify(binder).bindProducer(eq("baz"), eq(fooChannels.baz()),
|
||||
Mockito.<ProducerProperties>any());
|
||||
verify(binder).bindProducer(eq("qux"), eq(fooChannels.qux()),
|
||||
Mockito.<ProducerProperties>any());
|
||||
verifyNoMoreInteractions(binder);
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,8 @@ public class BinderAwareChannelResolverTests {
|
||||
bindings.put("foo", bindingProperties);
|
||||
this.channelBindingServiceProperties.setBindings(bindings);
|
||||
MessageConverterConfigurer messageConverterConfigurer = new MessageConverterConfigurer(
|
||||
this.channelBindingServiceProperties, new DefaultMessageBuilderFactory(), new CompositeMessageConverterFactory());
|
||||
this.channelBindingServiceProperties, new DefaultMessageBuilderFactory(),
|
||||
new CompositeMessageConverterFactory());
|
||||
messageConverterConfigurer.setBeanFactory(Mockito.mock(ConfigurableListableBeanFactory.class));
|
||||
messageConverterConfigurer.afterPropertiesSet();
|
||||
this.bindableChannelFactory = new DefaultBindableChannelFactory(messageConverterConfigurer);
|
||||
@@ -197,7 +198,8 @@ public class BinderAwareChannelResolverTests {
|
||||
private final Map<String, DirectChannel> destinations = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public Binding<MessageChannel> bindConsumer(String name, String group, MessageChannel inboundBindTarget, ConsumerProperties properties) {
|
||||
public Binding<MessageChannel> bindConsumer(String name, String group,
|
||||
MessageChannel inboundBindTarget, ConsumerProperties properties) {
|
||||
synchronized (destinations) {
|
||||
if (!destinations.containsKey(name)) {
|
||||
destinations.put(name, new DirectChannel());
|
||||
@@ -210,7 +212,8 @@ public class BinderAwareChannelResolverTests {
|
||||
|
||||
|
||||
@Override
|
||||
public Binding<MessageChannel> bindProducer(String name, MessageChannel outboundBindTarget, ProducerProperties properties) {
|
||||
public Binding<MessageChannel> bindProducer(String name,
|
||||
MessageChannel outboundBindTarget, ProducerProperties properties) {
|
||||
synchronized (destinations) {
|
||||
if (!destinations.containsKey(name)) {
|
||||
destinations.put(name, new DirectChannel());
|
||||
|
||||
@@ -59,11 +59,15 @@ public class BinderFactoryConfigurationTests {
|
||||
@Test
|
||||
public void loadBinderTypeRegistry() throws Exception {
|
||||
try {
|
||||
ConfigurableApplicationContext context = createBinderTestContext(new String[]{});
|
||||
ConfigurableApplicationContext context = createBinderTestContext(
|
||||
new String[] {});
|
||||
fail();
|
||||
}
|
||||
catch (BeanCreationException e) {
|
||||
assertThat(e.getMessage(),containsString("Cannot create binder factory, no `META-INF/spring.binders` " +
|
||||
assertThat(e.getMessage(),
|
||||
containsString(
|
||||
"Cannot create binder factory, no `META-INF/spring.binders` "
|
||||
+
|
||||
"resources found on the classpath"));
|
||||
}
|
||||
}
|
||||
@@ -97,20 +101,20 @@ public class BinderFactoryConfigurationTests {
|
||||
BinderFactory binderFactory = context.getBean(BinderFactory.class);
|
||||
|
||||
Binder binder1 = binderFactory.getBinder("binder1");
|
||||
assertThat(((StubBinder1)binder1).getName(), is(equalTo("foo")));
|
||||
assertThat(((StubBinder1) binder1).getName(), is(equalTo("foo")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadBinderTypeRegistryWithOneCustomBinderAndSharedEnvironment() throws Exception {
|
||||
ConfigurableApplicationContext context = createBinderTestContext(
|
||||
new String[] {"binder1"}, "binder1.name=foo",
|
||||
"spring.cloud.stream.binders.custom.properties.foo=bar",
|
||||
"spring.cloud.stream.binders.custom.type=binder1");
|
||||
"spring.cloud.stream.binders.custom.properties.foo=bar",
|
||||
"spring.cloud.stream.binders.custom.type=binder1");
|
||||
|
||||
BinderFactory binderFactory = context.getBean(BinderFactory.class);
|
||||
|
||||
Binder binder1 = binderFactory.getBinder("custom");
|
||||
assertThat(((StubBinder1)binder1).getName(), is(equalTo("foo")));
|
||||
assertThat(((StubBinder1) binder1).getName(), is(equalTo("foo")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -124,14 +128,14 @@ public class BinderFactoryConfigurationTests {
|
||||
BinderFactory binderFactory = context.getBean(BinderFactory.class);
|
||||
|
||||
Binder binder1 = binderFactory.getBinder("custom");
|
||||
assertThat(((StubBinder1)binder1).getName(),isEmptyOrNullString());
|
||||
assertThat(((StubBinder1) binder1).getName(), isEmptyOrNullString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadBinderTypeRegistryWithTwoBinders() throws Exception {
|
||||
|
||||
ConfigurableApplicationContext context = createBinderTestContext(
|
||||
new String[]{"binder1", "binder2"});
|
||||
new String[] { "binder1", "binder2" });
|
||||
BinderTypeRegistry binderTypeRegistry = context.getBean(BinderTypeRegistry.class);
|
||||
assertThat(binderTypeRegistry, notNullValue());
|
||||
assertThat(binderTypeRegistry.getAll().size(), equalTo(2));
|
||||
@@ -165,7 +169,8 @@ public class BinderFactoryConfigurationTests {
|
||||
|
||||
ConfigurableApplicationContext context =
|
||||
createBinderTestContext(
|
||||
new String[]{"binder1", "binder2"}, "spring.cloud.stream.defaultBinder:binder2");
|
||||
new String[] { "binder1", "binder2" },
|
||||
"spring.cloud.stream.defaultBinder:binder2");
|
||||
BinderTypeRegistry binderTypeRegistry = context.getBean(BinderTypeRegistry.class);
|
||||
assertThat(binderTypeRegistry, notNullValue());
|
||||
assertThat(binderTypeRegistry.getAll().size(), equalTo(2));
|
||||
@@ -186,10 +191,9 @@ public class BinderFactoryConfigurationTests {
|
||||
Binder defaultBinder = binderFactory.getBinder(null);
|
||||
assertThat(defaultBinder, is(binder2));
|
||||
}
|
||||
|
||||
|
||||
public static ConfigurableApplicationContext createBinderTestContext(String[] additionalClasspathDirectories,
|
||||
String... properties)
|
||||
throws IOException {
|
||||
String... properties) throws IOException {
|
||||
URL[] urls = ObjectUtils.isEmpty(additionalClasspathDirectories) ?
|
||||
new URL[0] : new URL[additionalClasspathDirectories.length];
|
||||
if (!ObjectUtils.isEmpty(additionalClasspathDirectories)) {
|
||||
@@ -208,5 +212,6 @@ public class BinderFactoryConfigurationTests {
|
||||
@Import({BinderFactoryConfiguration.class, PropertyPlaceholderAutoConfiguration.class})
|
||||
@EnableBinding
|
||||
public static class SimpleApplication {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@ import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Matchers.isNull;
|
||||
import static org.mockito.Matchers.same;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
|
||||
@@ -54,40 +54,44 @@ import org.springframework.util.ObjectUtils;
|
||||
*/
|
||||
public class HealthIndicatorsConfigurationTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void healthIndicatorsCheck() throws Exception {
|
||||
ConfigurableApplicationContext context =
|
||||
createBinderTestContext(
|
||||
new String[]{"binder1", "binder2"}, "spring.cloud.stream.defaultBinder:binder2");
|
||||
ConfigurableApplicationContext context = createBinderTestContext(
|
||||
new String[] { "binder1", "binder2" },
|
||||
"spring.cloud.stream.defaultBinder:binder2");
|
||||
|
||||
Binder binder1 = context.getBean(BinderFactory.class).getBinder("binder1");
|
||||
assertThat(binder1, instanceOf(StubBinder1.class));
|
||||
Binder binder2 = context.getBean(BinderFactory.class).getBinder("binder2");
|
||||
assertThat(binder2, instanceOf(StubBinder2.class));
|
||||
|
||||
CompositeHealthIndicator bindersHealthIndicator =
|
||||
context.getBean("bindersHealthIndicator", CompositeHealthIndicator.class);
|
||||
CompositeHealthIndicator bindersHealthIndicator = context
|
||||
.getBean("bindersHealthIndicator", CompositeHealthIndicator.class);
|
||||
|
||||
DirectFieldAccessor directFieldAccessor = new DirectFieldAccessor(bindersHealthIndicator);
|
||||
DirectFieldAccessor directFieldAccessor = new DirectFieldAccessor(
|
||||
bindersHealthIndicator);
|
||||
assertNotNull(bindersHealthIndicator);
|
||||
assertNotNull(context.getBean("testHealthIndicator1", CompositeHealthIndicator.class));
|
||||
assertNotNull(context.getBean("testHealthIndicator2", CompositeHealthIndicator.class));
|
||||
assertNotNull(
|
||||
context.getBean("testHealthIndicator1", CompositeHealthIndicator.class));
|
||||
assertNotNull(
|
||||
context.getBean("testHealthIndicator2", CompositeHealthIndicator.class));
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String,HealthIndicator> healthIndicators =
|
||||
(Map<String, HealthIndicator>) directFieldAccessor.getPropertyValue("indicators");
|
||||
Map<String, HealthIndicator> healthIndicators = (Map<String, HealthIndicator>) directFieldAccessor
|
||||
.getPropertyValue("indicators");
|
||||
assertThat(healthIndicators, IsMapContaining.hasKey("binder1"));
|
||||
assertThat(healthIndicators.get("binder1").health().getStatus(), CoreMatchers.equalTo(Status.UP));
|
||||
assertThat(healthIndicators.get("binder1").health().getStatus(),
|
||||
CoreMatchers.equalTo(Status.UP));
|
||||
assertThat(healthIndicators, IsMapContaining.hasKey("binder2"));
|
||||
assertThat(healthIndicators.get("binder2").health().getStatus(), CoreMatchers.equalTo(Status.UNKNOWN));
|
||||
assertThat(healthIndicators.get("binder2").health().getStatus(),
|
||||
CoreMatchers.equalTo(Status.UNKNOWN));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void healthIndicatorsCheckWhenDisabled() throws Exception {
|
||||
ConfigurableApplicationContext context =
|
||||
createBinderTestContext(
|
||||
new String[]{"binder1", "binder2"}, "spring.cloud.stream.defaultBinder:binder2",
|
||||
"management.health.binders.enabled:false");
|
||||
ConfigurableApplicationContext context = createBinderTestContext(
|
||||
new String[] { "binder1", "binder2" },
|
||||
"spring.cloud.stream.defaultBinder:binder2",
|
||||
"management.health.binders.enabled:false");
|
||||
|
||||
Binder binder1 = context.getBean(BinderFactory.class).getBinder("binder1");
|
||||
assertThat(binder1, instanceOf(StubBinder1.class));
|
||||
@@ -100,26 +104,28 @@ public class HealthIndicatorsConfigurationTests {
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException e) {
|
||||
}
|
||||
assertNotNull(context.getBean("testHealthIndicator1", CompositeHealthIndicator.class));
|
||||
assertNotNull(context.getBean("testHealthIndicator2", CompositeHealthIndicator.class));
|
||||
assertNotNull(
|
||||
context.getBean("testHealthIndicator1", CompositeHealthIndicator.class));
|
||||
assertNotNull(
|
||||
context.getBean("testHealthIndicator2", CompositeHealthIndicator.class));
|
||||
}
|
||||
|
||||
public static ConfigurableApplicationContext createBinderTestContext(String[] additionalClasspathDirectories,
|
||||
String... properties)
|
||||
throws IOException {
|
||||
URL[] urls = ObjectUtils.isEmpty(additionalClasspathDirectories) ?
|
||||
new URL[0] : new URL[additionalClasspathDirectories.length];
|
||||
public static ConfigurableApplicationContext createBinderTestContext(
|
||||
String[] additionalClasspathDirectories, String... properties)
|
||||
throws IOException {
|
||||
URL[] urls = ObjectUtils.isEmpty(additionalClasspathDirectories) ? new URL[0]
|
||||
: new URL[additionalClasspathDirectories.length];
|
||||
if (!ObjectUtils.isEmpty(additionalClasspathDirectories)) {
|
||||
for (int i = 0; i < additionalClasspathDirectories.length; i++) {
|
||||
urls[i] = new URL(new ClassPathResource(additionalClasspathDirectories[i]).getURL().toString() + "/");
|
||||
urls[i] = new URL(new ClassPathResource(additionalClasspathDirectories[i])
|
||||
.getURL().toString() + "/");
|
||||
}
|
||||
}
|
||||
ClassLoader classLoader = new URLClassLoader(urls, BinderFactoryConfigurationTests.class.getClassLoader());
|
||||
ClassLoader classLoader = new URLClassLoader(urls,
|
||||
BinderFactoryConfigurationTests.class.getClassLoader());
|
||||
return new SpringApplicationBuilder(SimpleSource.class)
|
||||
.resourceLoader(new DefaultResourceLoader(classLoader))
|
||||
.properties(properties)
|
||||
.web(false)
|
||||
.run();
|
||||
.properties(properties).web(false).run();
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@@ -141,5 +147,4 @@ public class HealthIndicatorsConfigurationTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -20,8 +20,6 @@ import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
@@ -48,14 +46,17 @@ public class ProcessorBindingTestsWithBindingTargets {
|
||||
@Autowired
|
||||
private Binder binder;
|
||||
|
||||
@Autowired @Bindings(TestProcessor.class)
|
||||
@Autowired
|
||||
@Bindings(TestProcessor.class)
|
||||
private Processor testProcessor;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testSourceOutputChannelBound() {
|
||||
verify(binder).bindConsumer(eq("testtock.0"), anyString(), eq(testProcessor.input()), Mockito.<ConsumerProperties>any());
|
||||
verify(binder).bindProducer(eq("testtock.1"), eq(testProcessor.output()), Mockito.<ProducerProperties>any());
|
||||
verify(binder).bindConsumer(eq("testtock.0"), anyString(),
|
||||
eq(testProcessor.input()), Mockito.<ConsumerProperties>any());
|
||||
verify(binder).bindProducer(eq("testtock.1"), eq(testProcessor.output()),
|
||||
Mockito.<ProducerProperties>any());
|
||||
}
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
|
||||
@@ -20,8 +20,6 @@ import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
@@ -21,8 +21,6 @@ import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
@@ -49,13 +47,15 @@ public class SinkBindingTestsWithBindingTargets {
|
||||
@Autowired
|
||||
private Binder binder;
|
||||
|
||||
@Autowired @Bindings(TestSink.class)
|
||||
@Autowired
|
||||
@Bindings(TestSink.class)
|
||||
private Sink testSink;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testSourceOutputChannelBound() {
|
||||
verify(binder).bindConsumer(eq("testtock"), anyString(), eq(testSink.input()), Mockito.<ConsumerProperties>any());
|
||||
verify(binder).bindConsumer(eq("testtock"), anyString(), eq(testSink.input()),
|
||||
Mockito.<ConsumerProperties>any());
|
||||
verifyNoMoreInteractions(binder);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,6 @@ import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
@@ -20,8 +20,6 @@ import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
@@ -29,4 +29,4 @@ public class StubBinder2ConfigurationB {
|
||||
public StubBinder2Dependency dependency() {
|
||||
return new StubBinder2Dependency();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.cloud.stream.binding;
|
||||
|
||||
|
||||
import static org.hamcrest.CoreMatchers.sameInstance;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
@@ -41,6 +40,11 @@ import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.cloud.stream.binder.Binder;
|
||||
@@ -59,11 +63,6 @@ import org.springframework.integration.support.DefaultMessageBuilderFactory;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.core.DestinationResolutionException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @author Mark Fisher
|
||||
@@ -86,18 +85,21 @@ public class ChannelBindingServiceTests {
|
||||
new BinderConfiguration(new BinderType("mock", new Class[]{MockBinderConfiguration.class}),
|
||||
new Properties(), true)));
|
||||
Binder binder = binderFactory.getBinder("mock");
|
||||
ChannelBindingService service = new ChannelBindingService(properties, binderFactory);
|
||||
ChannelBindingService service = new ChannelBindingService(properties,
|
||||
binderFactory);
|
||||
MessageChannel inputChannel = new DirectChannel();
|
||||
@SuppressWarnings("unchecked")
|
||||
Binding<MessageChannel> mockBinding = Mockito.mock(Binding.class);
|
||||
when(binder.bindConsumer(eq("foo"), isNull(String.class), same(inputChannel), any(ConsumerProperties.class)))
|
||||
.thenReturn(mockBinding);
|
||||
Collection<Binding<MessageChannel>> bindings = service.bindConsumer(inputChannel, inputChannelName);
|
||||
when(binder.bindConsumer(eq("foo"), isNull(String.class), same(inputChannel),
|
||||
any(ConsumerProperties.class))).thenReturn(mockBinding);
|
||||
Collection<Binding<MessageChannel>> bindings = service.bindConsumer(inputChannel,
|
||||
inputChannelName);
|
||||
assertThat(bindings.size(), is(1));
|
||||
Binding<MessageChannel> binding = bindings.iterator().next();
|
||||
assertThat(binding, sameInstance(mockBinding));
|
||||
service.unbindConsumers(inputChannelName);
|
||||
verify(binder).bindConsumer(eq("foo"), isNull(String.class), same(inputChannel), any(ConsumerProperties.class));
|
||||
verify(binder).bindConsumer(eq("foo"), isNull(String.class), same(inputChannel),
|
||||
any(ConsumerProperties.class));
|
||||
verify(binding).unbind();
|
||||
binderFactory.destroy();
|
||||
}
|
||||
@@ -113,13 +115,18 @@ public class ChannelBindingServiceTests {
|
||||
|
||||
properties.setBindings(bindingProperties);
|
||||
|
||||
DefaultBinderFactory<MessageChannel> binderFactory =
|
||||
new DefaultBinderFactory<>(Collections.singletonMap("mock",
|
||||
new BinderConfiguration(new BinderType("mock", new Class[]{MockBinderConfiguration.class}),
|
||||
new Properties(), true)));
|
||||
DefaultBinderFactory<MessageChannel> binderFactory = new DefaultBinderFactory<>(
|
||||
Collections
|
||||
.singletonMap("mock",
|
||||
new BinderConfiguration(
|
||||
new BinderType("mock",
|
||||
new Class[] {
|
||||
MockBinderConfiguration.class }),
|
||||
new Properties(), true)));
|
||||
|
||||
Binder binder = binderFactory.getBinder("mock");
|
||||
ChannelBindingService service = new ChannelBindingService(properties, binderFactory);
|
||||
ChannelBindingService service = new ChannelBindingService(properties,
|
||||
binderFactory);
|
||||
MessageChannel inputChannel = new DirectChannel();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -127,12 +134,13 @@ public class ChannelBindingServiceTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
Binding<MessageChannel> mockBinding2 = Mockito.mock(Binding.class);
|
||||
|
||||
when(binder.bindConsumer(eq("foo"), isNull(String.class), same(inputChannel), any(ConsumerProperties.class)))
|
||||
.thenReturn(mockBinding1);
|
||||
when(binder.bindConsumer(eq("bar"), isNull(String.class), same(inputChannel), any(ConsumerProperties.class)))
|
||||
.thenReturn(mockBinding2);
|
||||
when(binder.bindConsumer(eq("foo"), isNull(String.class), same(inputChannel),
|
||||
any(ConsumerProperties.class))).thenReturn(mockBinding1);
|
||||
when(binder.bindConsumer(eq("bar"), isNull(String.class), same(inputChannel),
|
||||
any(ConsumerProperties.class))).thenReturn(mockBinding2);
|
||||
|
||||
Collection<Binding<MessageChannel>> bindings = service.bindConsumer(inputChannel, "input");
|
||||
Collection<Binding<MessageChannel>> bindings = service.bindConsumer(inputChannel,
|
||||
"input");
|
||||
assertThat(bindings.size(), is(2));
|
||||
|
||||
Iterator<Binding<MessageChannel>> iterator = bindings.iterator();
|
||||
@@ -144,8 +152,10 @@ public class ChannelBindingServiceTests {
|
||||
|
||||
service.unbindConsumers("input");
|
||||
|
||||
verify(binder).bindConsumer(eq("foo"), isNull(String.class), same(inputChannel), any(ConsumerProperties.class));
|
||||
verify(binder).bindConsumer(eq("bar"), isNull(String.class), same(inputChannel), any(ConsumerProperties.class));
|
||||
verify(binder).bindConsumer(eq("foo"), isNull(String.class), same(inputChannel),
|
||||
any(ConsumerProperties.class));
|
||||
verify(binder).bindConsumer(eq("bar"), isNull(String.class), same(inputChannel),
|
||||
any(ConsumerProperties.class));
|
||||
verify(binding1).unbind();
|
||||
verify(binding2).unbind();
|
||||
|
||||
@@ -162,37 +172,48 @@ public class ChannelBindingServiceTests {
|
||||
final String inputChannelName = "input";
|
||||
bindingProperties.put(inputChannelName, props);
|
||||
properties.setBindings(bindingProperties);
|
||||
DefaultBinderFactory<MessageChannel> binderFactory =
|
||||
new DefaultBinderFactory<>(Collections.singletonMap("mock",
|
||||
new BinderConfiguration(new BinderType("mock", new Class[]{MockBinderConfiguration.class}),
|
||||
new Properties(), true)));
|
||||
DefaultBinderFactory<MessageChannel> binderFactory = new DefaultBinderFactory<>(
|
||||
Collections
|
||||
.singletonMap("mock",
|
||||
new BinderConfiguration(
|
||||
new BinderType("mock",
|
||||
new Class[] {
|
||||
MockBinderConfiguration.class }),
|
||||
new Properties(), true)));
|
||||
Binder binder = binderFactory.getBinder("mock");
|
||||
ChannelBindingService service = new ChannelBindingService(properties, binderFactory);
|
||||
ChannelBindingService service = new ChannelBindingService(properties,
|
||||
binderFactory);
|
||||
MessageChannel inputChannel = new DirectChannel();
|
||||
@SuppressWarnings("unchecked")
|
||||
Binding<MessageChannel> mockBinding = Mockito.mock(Binding.class);
|
||||
when(binder.bindConsumer(eq("foo"), eq("fooGroup"), same(inputChannel), any(ConsumerProperties.class)))
|
||||
.thenReturn(mockBinding);
|
||||
Collection<Binding<MessageChannel>> bindings = service.bindConsumer(inputChannel, inputChannelName);
|
||||
when(binder.bindConsumer(eq("foo"), eq("fooGroup"), same(inputChannel),
|
||||
any(ConsumerProperties.class))).thenReturn(mockBinding);
|
||||
Collection<Binding<MessageChannel>> bindings = service.bindConsumer(inputChannel,
|
||||
inputChannelName);
|
||||
assertThat(bindings.size(), is(1));
|
||||
Binding<MessageChannel> binding = bindings.iterator().next();
|
||||
assertThat(binding, sameInstance(mockBinding));
|
||||
|
||||
service.unbindConsumers(inputChannelName);
|
||||
verify(binder).bindConsumer(eq("foo"), eq(props.getGroup()), same(inputChannel), any(ConsumerProperties.class));
|
||||
verify(binder).bindConsumer(eq("foo"), eq(props.getGroup()), same(inputChannel),
|
||||
any(ConsumerProperties.class));
|
||||
verify(binding).unbind();
|
||||
binderFactory.destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkDynamicBinding () {
|
||||
public void checkDynamicBinding() {
|
||||
|
||||
ChannelBindingServiceProperties properties = new ChannelBindingServiceProperties();
|
||||
DynamicDestinationsBindable dynamicDestinationsBindable = new DynamicDestinationsBindable();
|
||||
DefaultBinderFactory<MessageChannel> binderFactory =
|
||||
new DefaultBinderFactory<>(Collections.singletonMap("mock",
|
||||
new BinderConfiguration(new BinderType("mock", new Class[]{MockBinderConfiguration.class}),
|
||||
new Properties(), true)));
|
||||
DefaultBinderFactory<MessageChannel> binderFactory = new DefaultBinderFactory<>(
|
||||
Collections
|
||||
.singletonMap("mock",
|
||||
new BinderConfiguration(
|
||||
new BinderType("mock",
|
||||
new Class[] {
|
||||
MockBinderConfiguration.class }),
|
||||
new Properties(), true)));
|
||||
Binder binder = binderFactory.getBinder("mock");
|
||||
|
||||
MessageChannel inputChannel = new DirectChannel();
|
||||
@@ -200,14 +221,18 @@ public class ChannelBindingServiceTests {
|
||||
Binding<MessageChannel> mockBinding = Mockito.mock(Binding.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
final AtomicReference<MessageChannel> dynamic = new AtomicReference<>();
|
||||
when(binder.bindProducer(
|
||||
matches("bar"), any(DirectChannel.class), any(ProducerProperties.class))).thenReturn(mockBinding);
|
||||
BinderAwareChannelResolver resolver = new BinderAwareChannelResolver(binderFactory, properties, dynamicDestinationsBindable,
|
||||
new DefaultBindableChannelFactory(new MessageConverterConfigurer(properties, new DefaultMessageBuilderFactory(), new CompositeMessageConverterFactory())));
|
||||
ConfigurableListableBeanFactory beanFactory = mock(ConfigurableListableBeanFactory.class);
|
||||
when(binder.bindProducer(matches("bar"), any(DirectChannel.class),
|
||||
any(ProducerProperties.class))).thenReturn(mockBinding);
|
||||
BinderAwareChannelResolver resolver = new BinderAwareChannelResolver(
|
||||
binderFactory, properties, dynamicDestinationsBindable,
|
||||
new DefaultBindableChannelFactory(new MessageConverterConfigurer(
|
||||
properties, new DefaultMessageBuilderFactory(),
|
||||
new CompositeMessageConverterFactory())));
|
||||
ConfigurableListableBeanFactory beanFactory = mock(
|
||||
ConfigurableListableBeanFactory.class);
|
||||
when(beanFactory.getBean("mock:bar", MessageChannel.class))
|
||||
.thenThrow(new NoSuchBeanDefinitionException(MessageChannel.class));
|
||||
doAnswer(new Answer<Void>(){
|
||||
doAnswer(new Answer<Void>() {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
@@ -227,7 +252,8 @@ public class ChannelBindingServiceTests {
|
||||
resolver.setBeanFactory(beanFactory);
|
||||
MessageChannel resolved = resolver.resolveDestination("mock:bar");
|
||||
assertThat(resolved, sameInstance(dynamic.get()));
|
||||
verify(binder).bindProducer(eq("bar"), eq(dynamic.get()), any(ProducerProperties.class));
|
||||
verify(binder).bindProducer(eq("bar"), eq(dynamic.get()),
|
||||
any(ProducerProperties.class));
|
||||
properties.setDynamicDestinations(new String[] { "mock:bar" });
|
||||
resolved = resolver.resolveDestination("mock:bar");
|
||||
assertThat(resolved, sameInstance(dynamic.get()));
|
||||
@@ -237,7 +263,8 @@ public class ChannelBindingServiceTests {
|
||||
fail();
|
||||
}
|
||||
catch (DestinationResolutionException e) {
|
||||
assertThat(e.getMessage(), containsString("Failed to find MessageChannel bean with name 'mock:bar'"));
|
||||
assertThat(e.getMessage(), containsString(
|
||||
"Failed to find MessageChannel bean with name 'mock:bar'"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,18 +307,24 @@ public class ChannelBindingServiceTests {
|
||||
final String inputChannelName = "input";
|
||||
bindingProperties.put(inputChannelName, props);
|
||||
serviceProperties.setBindings(bindingProperties);
|
||||
DefaultBinderFactory<MessageChannel> binderFactory =
|
||||
new DefaultBinderFactory<>(Collections.singletonMap("mock",
|
||||
new BinderConfiguration(new BinderType("mock", new Class[]{MockBinderConfiguration.class}),
|
||||
new Properties(), true)));
|
||||
ChannelBindingService service = new ChannelBindingService(serviceProperties, binderFactory);
|
||||
DefaultBinderFactory<MessageChannel> binderFactory = new DefaultBinderFactory<>(
|
||||
Collections
|
||||
.singletonMap("mock",
|
||||
new BinderConfiguration(
|
||||
new BinderType("mock",
|
||||
new Class[] {
|
||||
MockBinderConfiguration.class }),
|
||||
new Properties(), true)));
|
||||
ChannelBindingService service = new ChannelBindingService(serviceProperties,
|
||||
binderFactory);
|
||||
MessageChannel inputChannel = new DirectChannel();
|
||||
try {
|
||||
service.bindConsumer(inputChannel, inputChannelName);
|
||||
fail("Consumer properties should be validated.");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
assertTrue(e.getMessage().contains("Concurrency should be greater than zero."));
|
||||
assertTrue(
|
||||
e.getMessage().contains("Concurrency should be greater than zero."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
21
src/checkstyle/checkstyle.xml
Normal file
21
src/checkstyle/checkstyle.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module PUBLIC
|
||||
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
|
||||
<module name="Checker">
|
||||
<module name="TreeWalker">
|
||||
<!-- this. in front of fields -->
|
||||
<module name="RequireThis">
|
||||
<property name="checkMethods" value="false"/>
|
||||
</module>
|
||||
<!-- tabs instead of spaces -->
|
||||
<module name="RegexpSinglelineJava">
|
||||
<property name="format" value="^\t* "/>
|
||||
<property name="message" value="Indent must use tab characters"/>
|
||||
<property name="ignoreComments" value="true"/>
|
||||
</module>
|
||||
<module name="UnusedImports"/>
|
||||
<module name="RedundantImport"/>
|
||||
<module name="NeedBraces"/>
|
||||
</module>
|
||||
</module>
|
||||
Reference in New Issue
Block a user