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:
Marius Bogoevici
2016-04-15 00:02:11 -04:00
committed by Ilayaperumal Gopinathan
parent 0bbabaf705
commit 147a0cb0bc
27 changed files with 502 additions and 369 deletions

41
pom.xml
View File

@@ -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>

View File

@@ -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
*/

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -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() {

View File

@@ -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;
}

View File

@@ -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() {

View File

@@ -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();
}
}
}

View File

@@ -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) {

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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());

View File

@@ -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 {
}
}

View File

@@ -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;

View File

@@ -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 {
}
}
}

View File

@@ -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)

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -29,4 +29,4 @@ public class StubBinder2ConfigurationB {
public StubBinder2Dependency dependency() {
return new StubBinder2Dependency();
}
}
}

View File

@@ -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."));
}
}
}

View 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>