GH-213 Merge Binder SPI into Core

- Moved contents of `spring-cloud-stream-binder-spi` into `spring-cloud-stream`
- Removed `spring-cloud-stream-binder-local` and used local binder implementation for tests exclusively
This commit is contained in:
Marius Bogoevici
2015-11-30 16:59:21 -05:00
parent 6f1f246dfb
commit bcff75b20b
33 changed files with 22 additions and 488 deletions

View File

@@ -99,11 +99,6 @@
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-spi</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-test</artifactId>

View File

@@ -20,9 +20,7 @@
<spring-xd.version>1.2.1.RELEASE</spring-xd.version>
</properties>
<modules>
<module>spring-cloud-stream-binder-spi</module>
<module>spring-cloud-stream-binder-test</module>
<module>spring-cloud-stream-binder-local</module>
<module>spring-cloud-stream-binder-rabbit</module>
<module>spring-cloud-stream-binder-redis</module>
<module>spring-cloud-stream-binder-kafka</module>

View File

@@ -27,7 +27,7 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-spi</artifactId>
<artifactId>spring-cloud-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>

View File

@@ -54,6 +54,7 @@ import org.springframework.messaging.support.GenericMessage;
* @author Gary Russell
*/
@Ignore
public class RawModeKafkaBinderTests extends KafkaBinderTests {
@Override

View File

@@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-stream-binder-local</artifactId>
<packaging>jar</packaging>
<name>spring-cloud-stream-binder-local</name>
<description>Local(in memory) binder implementation</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binders-parent</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-spi</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -1,34 +0,0 @@
/*
* Copyright 2015 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.stream.binder.local.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.stream.binder.Binder;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
/**
* Auto configuration for Local (in-memory) {@link Binder}.
*
* @author Ilayaperumal Gopinathan
*/
@Configuration
@ConditionalOnMissingBean(Binder.class)
@Import(LocalMessageChannelBinderConfiguration.class)
@PropertySource("classpath:/META-INF/spring-cloud-stream/local-binder.properties")
public class LocalBinderAutoConfiguration {
}

View File

@@ -1,66 +0,0 @@
/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.stream.binder.local.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author David Turanski
*/
@ConfigurationProperties(prefix = "spring.cloud.stream.binder.local.executor")
class LocalExecutorConfigurationProperties {
private int corePoolSize;
private int maxPoolSize;
private int queueSize = Integer.MAX_VALUE;
private int keepAliveSeconds;
public int getCorePoolSize() {
return corePoolSize;
}
public void setCorePoolSize(int corePoolSize) {
this.corePoolSize = corePoolSize;
}
public int getMaxPoolSize() {
return maxPoolSize;
}
public void setMaxPoolSize(int maxPoolSize) {
this.maxPoolSize = maxPoolSize;
}
public int getQueueSize() {
return queueSize;
}
public void setQueueSize(int queueSize) {
this.queueSize = queueSize;
}
public int getKeepAliveSeconds() {
return keepAliveSeconds;
}
public void setKeepAliveSeconds(int keepAliveSeconds) {
this.keepAliveSeconds = keepAliveSeconds;
}
}

View File

@@ -1,71 +0,0 @@
/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.stream.binder.local.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.stream.binder.local.LocalMessageChannelBinder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.scheduling.PollerMetadata;
import org.springframework.scheduling.support.PeriodicTrigger;
/**
* @author David Turanski
*/
@Configuration
@ConfigurationProperties(prefix = "spring.cloud.stream.binder.local")
@EnableConfigurationProperties(LocalExecutorConfigurationProperties.class)
public class LocalMessageChannelBinderConfiguration {
private int queueSize = Integer.MAX_VALUE;
private int polling;
@Autowired
LocalExecutorConfigurationProperties localExecutorConfigurationProperties;
@Bean
public LocalMessageChannelBinder localMessageChannelBinder() {
LocalMessageChannelBinder localMessageChannelBinder = new LocalMessageChannelBinder();
localMessageChannelBinder.setExecutorCorePoolSize(localExecutorConfigurationProperties.getCorePoolSize());
localMessageChannelBinder.setExecutorKeepAliveSeconds(localExecutorConfigurationProperties.getKeepAliveSeconds());
localMessageChannelBinder.setExecutorMaxPoolSize(localExecutorConfigurationProperties.getMaxPoolSize());
localMessageChannelBinder.setExecutorQueueSize(localExecutorConfigurationProperties.getQueueSize());
if (polling > 0) {
PollerMetadata pollerMetadata = new PollerMetadata();
pollerMetadata.setTrigger(new PeriodicTrigger(polling));
localMessageChannelBinder.setPoller(pollerMetadata);
}
localMessageChannelBinder.setQueueSize(queueSize);
return localMessageChannelBinder;
}
public void setQueueSize(int queueSize) {
this.queueSize = queueSize;
}
public void setPolling(int polling) {
this.polling = polling;
}
}

View File

@@ -1,5 +0,0 @@
spring.cloud.stream.binder.local.polling: 1000
spring.cloud.stream.binder.local.executor.corePoolSize: 0
spring.cloud.stream.binder.local.executor.maxPoolSize: 400
#spring.cloud.stream.binder.local.executor.queueSize: # defaults to Integer.MAX_VALUE
spring.cloud.stream.binder.local.executor.keepAliveSeconds: 60

View File

@@ -1,2 +0,0 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration:\
org.springframework.cloud.stream.binder.local.config.LocalBinderAutoConfiguration

View File

@@ -1,195 +0,0 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.stream.binder.local;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.util.Collection;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.cloud.stream.binder.AbstractBinderTests;
import org.springframework.cloud.stream.binder.Binder;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.interceptor.WireTap;
import org.springframework.integration.support.DefaultMessageBuilderFactory;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.support.utils.IntegrationUtils;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.MessagingException;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/**
* @author Gary Russell
* @author David Turanski
* @since 1.0
*/
public class LocalBinderTests extends AbstractBinderTests {
@Override
protected Binder<MessageChannel> getBinder() throws Exception {
LocalMessageChannelBinder binder = new LocalMessageChannelBinder();
GenericApplicationContext applicationContext = new GenericApplicationContext();
applicationContext.getBeanFactory().registerSingleton(
IntegrationUtils.INTEGRATION_MESSAGE_BUILDER_FACTORY_BEAN_NAME,
new DefaultMessageBuilderFactory());
applicationContext.refresh();
binder.setApplicationContext(applicationContext);
binder.setExecutorCorePoolSize(2);
binder.setExecutorMaxPoolSize(10);
binder.setExecutorKeepAliveSeconds(59);
binder.setExecutorQueueSize(Integer.MAX_VALUE - 1);
binder.afterPropertiesSet();
return binder;
}
@Override
protected Collection<?> getBindings(Binder<MessageChannel> testBinder) {
return getBindingsFromBinder(testBinder);
}
@Test
public void testProps() throws Exception {
LocalMessageChannelBinder binder = (LocalMessageChannelBinder) getBinder();
ThreadPoolTaskExecutor exec = TestUtils.getPropertyValue(binder, "executor", ThreadPoolTaskExecutor.class);
assertEquals(2, exec.getCorePoolSize());
assertEquals(10, exec.getMaxPoolSize());
assertEquals(59, exec.getKeepAliveSeconds());
Assert.assertEquals(Integer.MAX_VALUE - 1, TestUtils.getPropertyValue(exec, "queueCapacity"));
}
@Test
public void testPayloadConversionNotNeededExplicitType() throws Exception {
LocalMessageChannelBinder binder = (LocalMessageChannelBinder) getBinder();
verifyPayloadConversion(new TestPayload(), binder);
}
@Test
public void testNoPayloadConversionByDefault() throws Exception {
LocalMessageChannelBinder binder = (LocalMessageChannelBinder) getBinder();
verifyPayloadConversion(new TestPayload(), binder);
}
@Test
public void testTapDoesntHurtStream() throws Exception {
LocalMessageChannelBinder binder = (LocalMessageChannelBinder) getBinder();
DirectChannel moduleOutputChannel = new DirectChannel();
moduleOutputChannel.setBeanName("bangOut");
DirectChannel tapChannel = new DirectChannel();
tapChannel.setBeanName("tapChannel");
WireTap tap = new WireTap(tapChannel);
moduleOutputChannel.addInterceptor(tap);
binder.bindProducer("bang.0", moduleOutputChannel, null);
final AtomicBoolean messageReceived = new AtomicBoolean();
final AtomicReference<Thread> streamThread = new AtomicReference<Thread>();
binder.bindConsumer("bang.0", new DirectChannel() {
@Override
protected boolean doSend(Message<?> message, long timeout) {
messageReceived.set(true);
streamThread.set(Thread.currentThread());
return true;
}
}, null);
final CountDownLatch tapped = new CountDownLatch(1);
final AtomicReference<Thread> tapThread = new AtomicReference<Thread>();
binder.bindPubSubProducer("tap:stream:bang.0", tapChannel, null);
binder.bindPubSubConsumer("tap:stream:bang.0", new DirectChannel() {
@Override
protected boolean doSend(Message<?> message, long timeout) {
tapThread.set(Thread.currentThread());
tapped.countDown();
throw new RuntimeException("bang");
}
}, null, null);
moduleOutputChannel.send(new GenericMessage<String>("Foo"));
assertTrue(tapped.await(10, TimeUnit.SECONDS));
assertTrue(messageReceived.get());
assertSame(Thread.currentThread(), streamThread.get());
assertNotNull(tapThread.get());
assertNotSame(Thread.currentThread(), tapThread.get());
}
private void verifyPayloadConversion(final Object expectedValue, final LocalMessageChannelBinder binder) {
DirectChannel myChannel = new DirectChannel();
binder.bindConsumer("in", myChannel, null);
DirectChannel input = binder.getBean("in", DirectChannel.class);
assertNotNull(input);
final AtomicBoolean msgSent = new AtomicBoolean(false);
myChannel.subscribe(new MessageHandler() {
@Override
public void handleMessage(Message<?> message) throws MessagingException {
assertEquals(expectedValue, message.getPayload());
msgSent.set(true);
}
});
Message<TestPayload> msg = MessageBuilder.withPayload(new TestPayload())
.setHeader(MessageHeaders.CONTENT_TYPE, MediaType.ALL_VALUE).build();
input.send(msg);
assertTrue(msgSent.get());
}
@Override @Ignore // TODO
public void testSendAndReceivePubSub() throws Exception {
}
@Override @Ignore // TODO
public void createInboundPubSubBeforeOutboundPubSub() throws Exception {
}
static class TestPayload {
@Override
public String toString() {
return "foo";
}
@Override
public boolean equals(Object other) {
return (other instanceof TestPayload && this.toString().equals(other.toString()));
}
@Override
public int hashCode() {
return this.toString().hashCode();
}
}
}

View File

@@ -25,7 +25,7 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-spi</artifactId>
<artifactId>spring-cloud-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>

View File

@@ -25,7 +25,7 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-spi</artifactId>
<artifactId>spring-cloud-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>

View File

@@ -1,42 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-stream-binder-spi</artifactId>
<packaging>jar</packaging>
<name>spring-cloud-stream-binder-spi</name>
<description>SPI for binder implementations</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binders-parent</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -41,7 +41,7 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-spi</artifactId>
<artifactId>spring-cloud-stream</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -20,16 +20,11 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-spi</artifactId>
<artifactId>spring-cloud-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -35,21 +35,6 @@
<artifactId>spring-cloud-stream-tuple</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-local</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-redis</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
@@ -60,6 +45,22 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
</dependencies>
</project>