Remove xd-runner

This commit is contained in:
Ilayaperumal Gopinathan
2015-07-13 19:45:17 -07:00
parent 5377eaf258
commit 09c0cf5573
9 changed files with 1 additions and 721 deletions

View File

@@ -30,7 +30,6 @@
<module>spring-cloud-streams-bindings</module>
<module>spring-cloud-streams-codec</module>
<module>spring-cloud-streams-common</module>
<module>spring-xd-runner</module>
<module>spring-cloud-streams-samples</module>
<module>docs</module>
</modules>

View File

@@ -23,7 +23,7 @@
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-xd-runner</artifactId>
<artifactId>spring-cloud-streams</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>

View File

@@ -1,47 +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-xd-runner</artifactId>
<packaging>jar</packaging>
<name>spring-xd-runner</name>
<description>Demo project for Spring XD Modules as apps</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-streams-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.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-streams</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-streams-codec</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.xd</groupId>
<artifactId>spring-xd-module</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -1,144 +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.streams.xd;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.xd.dirt.plugins.stream.ModuleTypeConversionPluginMetadataResolver;
import org.springframework.xd.module.ModuleDefinition;
import org.springframework.xd.module.ModuleDefinitions;
import org.springframework.xd.module.ModuleType;
import org.springframework.xd.module.options.DefaultModuleOptionsMetadataResolver;
import org.springframework.xd.module.options.DelegatingModuleOptionsMetadataResolver;
import org.springframework.xd.module.options.EnvironmentAwareModuleOptionsMetadataResolver;
import org.springframework.xd.module.options.ModuleOption;
import org.springframework.xd.module.options.ModuleOptionsMetadata;
import org.springframework.xd.module.options.ModuleOptionsMetadataResolver;
/**
* Initialize the application context with default values for the module options.
*
* @author Dave Syer
*
*/
@Configuration
@EnableConfigurationProperties
@Order(Ordered.HIGHEST_PRECEDENCE + 10)
public class ModuleOptionsPropertySourceInitializer implements
ApplicationContextInitializer<ConfigurableApplicationContext> {
@Autowired
private ModuleProperties module = new ModuleProperties();
@Autowired(required = false)
private EnvironmentAwareModuleOptionsMetadataResolver wrapper;
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
ModuleOptionsMetadataResolver resolver = moduleOptionsMetadataResolver(environment);
ModuleOptionsMetadata resolved = resolver
.resolve(getModuleDefinition(applicationContext));
Map<String, Object> map = new LinkedHashMap<String, Object>();
for (ModuleOption option : resolved) {
if (option.getDefaultValue() != null) {
map.put(option.getName(), option.getDefaultValue());
}
}
insert(environment, new MapPropertySource("moduleDefaults", map));
applicationContext.getBeanFactory().registerSingleton(
"spring.cloud.channels.CONFIGURATION_PROPERTIES", this.module);
}
private ModuleDefinition getModuleDefinition(
ConfigurableApplicationContext applicationContext) {
String location = "file:.";
ClassLoader classLoader = applicationContext.getClassLoader();
if (classLoader instanceof URLClassLoader) {
URL[] urls = ((URLClassLoader) classLoader).getURLs();
String firstUrl = urls[0].toString();
if (firstUrl.startsWith("jar:") && firstUrl.endsWith("!/")) {
location = firstUrl.substring(4, firstUrl.length() - 2);
}
}
return ModuleDefinitions.simple(this.module.getName(),
ModuleType.valueOf(this.module.getType()), location);
}
private void insert(ConfigurableEnvironment environment, MapPropertySource source) {
environment.getPropertySources().addLast(source);
}
private ModuleOptionsMetadataResolver moduleOptionsMetadataResolver(
Environment environment) {
List<ModuleOptionsMetadataResolver> delegates = new ArrayList<ModuleOptionsMetadataResolver>();
delegates.add(defaultResolver());
delegates.add(new ModuleTypeConversionPluginMetadataResolver());
DelegatingModuleOptionsMetadataResolver delegatingResolver = new DelegatingModuleOptionsMetadataResolver();
delegatingResolver.setDelegates(delegates);
ModuleOptionsMetadataResolver resolver = delegatingResolver;
if (this.wrapper != null) {
this.wrapper.setDelegate(delegatingResolver);
resolver = this.wrapper;
}
return resolver;
}
@Bean
// TODO: allow override of this
public DefaultModuleOptionsMetadataResolver defaultResolver() {
DefaultModuleOptionsMetadataResolver defaultResolver = new DefaultModuleOptionsMetadataResolver();
return defaultResolver;
}
@ConditionalOnExpression("'${xd.module.config.location:${xd.config.home:}}'!=''")
protected static class EnvironmentAwareModuleOptionsMetadataResolverConfiguration {
@Bean
public EnvironmentAwareModuleOptionsMetadataResolver environmentAwareModuleOptionsMetadataResolver() {
return new EnvironmentAwareModuleOptionsMetadataResolver();
}
}
@Configuration
@ConditionalOnMissingBean(value = ModuleProperties.class, search = SearchStrategy.CURRENT)
protected static class ModulePropertiesConfiguration {
@Bean(name = "spring.cloud.channels.CONFIGURATION_PROPERTIES")
public ModuleProperties moduleProperties() {
return new ModuleProperties();
}
}
}

View File

@@ -1,155 +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.streams.xd;
import org.springframework.cloud.streams.config.ChannelBindingProperties;
import org.springframework.util.Assert;
import org.springframework.xd.dirt.integration.bus.BusUtils;
/**
* @author Dave Syer
*
*/
public class ModuleProperties extends ChannelBindingProperties {
private String group = "group";
private String name = "module";
private int index = 0;
private String type = "processor";
private Tap tap;
public String getType() {
return this.type;
}
public void setType(String type) {
this.type = type;
}
public String getGroup() {
return this.group;
}
public void setGroup(String group) {
this.group = group;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getIndex() {
return this.index;
}
public void setIndex(int index) {
this.index = index;
}
@Override
public String getOutputChannelName() {
String name = super.getOutputChannelName();
if (ChannelBindingProperties.DEFAULT_CHANNEL_NAME.equals(name)) {
return BusUtils.constructPipeName(this.group, this.index);
}
return name;
}
@Override
public String getInputChannelName() {
if (isTap()) {
return String.format("%s.%s.%s",
BusUtils.constructTapPrefix(this.tap.getGroup()), this.tap.getName(),
this.tap.getIndex());
}
String name = super.getInputChannelName();
if (ChannelBindingProperties.DEFAULT_CHANNEL_NAME.equals(name)) {
return BusUtils.constructPipeName(this.group, this.index > 0 ? this.index - 1
: this.index);
}
return name;
}
@Override
public String getTapChannelName() {
return getTapChannelName(this.group);
}
@Override
public String getTapChannelName(String prefix) {
Assert.isTrue(!this.type.equals("job"), "Job module type not supported.");
// for Stream return channel name with indexed elements
return String.format("%s.%s.%s", BusUtils.constructTapPrefix(prefix), this.name,
this.index);
}
public Tap getTap() {
return this.tap;
}
public void setTap(Tap tap) {
this.tap = tap;
}
private boolean isTap() {
if (this.tap != null) {
Assert.state(this.tap.getName() != null, "Tap name not provided");
Assert.state(!this.tap.getGroup().equals(this.group),
"Tap group cannot be the same as module group");
}
return this.tap != null;
}
public static class Tap {
private String group = "group";
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
private int index = 0;
public String getGroup() {
return this.group;
}
public void setGroup(String group) {
this.group = group;
}
public int getIndex() {
return this.index;
}
public void setIndex(int index) {
this.index = index;
}
}
}

View File

@@ -1,41 +0,0 @@
/*
* Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.xd.dirt.plugins.stream;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.MediaType;
import org.springframework.util.MimeType;
/**
* A custom converter for {@link MediaType} that accepts a plain java class name as a shorthand for
* {@code application/x-java-object;type=the.qualified.ClassName}.
*
*
* @author Eric Bottard
* @author David Turanski
*/
public class CustomMimeTypeConverter implements Converter<String, MimeType> {
@Override
public MimeType convert(String source) {
if (!source.contains("/")) {
return MimeType.valueOf("application/x-java-object;type=" + source);
}
return MimeType.valueOf(source);
}
}

View File

@@ -1,117 +0,0 @@
/*
* Copyright 2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.xd.dirt.plugins.stream;
import static org.springframework.xd.module.ModuleType.processor;
import static org.springframework.xd.module.ModuleType.sink;
import static org.springframework.xd.module.ModuleType.source;
import java.util.ArrayList;
import java.util.List;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.util.MimeType;
import org.springframework.xd.module.ModuleDefinition;
import org.springframework.xd.module.ModuleType;
import org.springframework.xd.module.options.FlattenedCompositeModuleOptionsMetadata;
import org.springframework.xd.module.options.ModuleOptionsMetadata;
import org.springframework.xd.module.options.ModuleOptionsMetadataResolver;
import org.springframework.xd.module.options.PojoModuleOptionsMetadata;
import org.springframework.xd.module.options.spi.ModuleOption;
/**
* A {@link ModuleOptionsMetadataResolver} that will dynamically add {@code inputType} and {@code outputType} options to
* every module, according to their type.
*
* @see ModuleTypeConversionPlugin
* @author Eric Bottard
* @author David Turanski
*/
public class ModuleTypeConversionPluginMetadataResolver implements ModuleOptionsMetadataResolver {
private final GenericConversionService conversionService = new GenericConversionService();
public ModuleTypeConversionPluginMetadataResolver() {
conversionService.addConverter(new CustomMimeTypeConverter());
}
@Override
public ModuleOptionsMetadata resolve(ModuleDefinition moduleDefinition) {
List<ModuleOptionsMetadata> moms = new ArrayList<ModuleOptionsMetadata>();
ModuleType type = moduleDefinition.getType();
if (type == source || type == processor) {
moms.add(new PojoModuleOptionsMetadata(OutputOptionsMetadata.class, conversionService));
}
if (type == sink || type == processor) {
moms.add(new PojoModuleOptionsMetadata(InputOptionsMetadata.class, conversionService));
}
// Don't force deep layering if it's not needed
switch (moms.size()) {
case 0:
return null;
case 1:
return moms.iterator().next();
default:
return new FlattenedCompositeModuleOptionsMetadata(moms);
}
}
/**
* Provides info about the {@code inputType} option.
*
* @author Eric Bottard
*/
@SuppressWarnings("unused")
private static class InputOptionsMetadata {
private MimeType inputType;
public MimeType getInputType() {
return inputType;
}
@ModuleOption("how this module should interpret messages it consumes")
public void setInputType(MimeType inputType) {
this.inputType = inputType;
}
}
/**
* Provides info about the {@code outputType} option.
*
* @author Eric Bottard
*/
@SuppressWarnings("unused")
private static class OutputOptionsMetadata {
private MimeType outputType;
public MimeType getOutputType() {
return outputType;
}
@ModuleOption("how this module should emit messages it produces")
public void setOutputType(MimeType outputType) {
this.outputType = outputType;
}
}
}

View File

@@ -1,2 +0,0 @@
org.springframework.cloud.bootstrap.BootstrapConfiguration:\
org.springframework.cloud.streams.xd.ModuleOptionsPropertySourceInitializer

View File

@@ -1,213 +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.streams.xd;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.cloud.streams.adapter.ChannelBinding;
import org.springframework.cloud.streams.adapter.ChannelBindingAdapter;
import org.springframework.cloud.streams.adapter.InputChannelBinding;
import org.springframework.cloud.streams.adapter.OutputChannelBinding;
import org.springframework.cloud.streams.config.ChannelBindingAdapterConfiguration;
import org.springframework.cloud.streams.utils.BeanDefinitionRegistryUtils;
import org.springframework.cloud.streams.xd.ChannelBindingAdapterConfigurationTests.Empty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.xd.dirt.integration.bus.local.LocalMessageBus;
/**
* @author Dave Syer
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Empty.class)
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
public class ChannelBindingAdapterConfigurationTests {
@Autowired
private DefaultListableBeanFactory context;
@Autowired
private ChannelBindingAdapter adapter;
@Autowired
private ChannelBindingAdapterConfiguration configuration;
@Autowired
private ModuleProperties module;
@Before
public void init() {
}
@Test
public void oneOutput() throws Exception {
BeanDefinitionRegistryUtils.registerOutputChannelBeanDefinition("output", context);
this.context.registerSingleton("output", new DirectChannel());
refresh();
Collection<OutputChannelBinding> channels = this.adapter.getChannelsMetadata()
.getOutputChannels();
assertEquals(1, channels.size());
assertEquals("group.0", channels.iterator().next().getRemoteName());
assertEquals("tap:stream:group.module.0", channels.iterator().next()
.getTapChannelName());
}
@Test
public void oneInput() throws Exception {
BeanDefinitionRegistryUtils.registerInputChannelBeanDefinition("input",context);
refresh();
Collection<InputChannelBinding> channels = this.adapter.getChannelsMetadata()
.getInputChannels();
assertEquals(1, channels.size());
assertEquals("group.0", channels.iterator().next().getRemoteName());
}
private void refresh() {
this.configuration.refresh();
Collection<OutputChannelBinding> channels = this.adapter.getChannelsMetadata()
.getOutputChannels();
for (OutputChannelBinding channel : channels) {
channel.setTapped(true);
}
this.adapter.setOutputChannels(channels);
this.adapter.start();
}
@Test
public void oneOutputTopic() throws Exception {
BeanDefinitionRegistryUtils.registerOutputChannelBeanDefinition("output.topic:", this.context);
refresh();
Collection<OutputChannelBinding> channels = this.adapter.getChannelsMetadata()
.getOutputChannels();
assertEquals(1, channels.size());
assertEquals("topic:group.0", channels.iterator().next().getRemoteName());
assertEquals("tap:stream:group.module.0", channels.iterator().next()
.getTapChannelName());
}
@Test
public void oneOutputOverrideName() throws Exception {
this.module.setGroup("mine");
this.module.setName("foo");
this.module.setIndex(2);
BeanDefinitionRegistryUtils.registerOutputChannelBeanDefinition("output.topic:", this.context);
refresh();
Collection<OutputChannelBinding> channels = this.adapter.getChannelsMetadata()
.getOutputChannels();
assertEquals(1, channels.size());
assertEquals("topic:mine.2", channels.iterator().next().getRemoteName());
assertEquals("tap:stream:mine.foo.2", channels.iterator().next()
.getTapChannelName());
}
@Test
public void oneInputTopic() throws Exception {
BeanDefinitionRegistryUtils.registerInputChannelBeanDefinition("input.topic:", this.context);
refresh();
Collection<InputChannelBinding> channels = this.adapter.getChannelsMetadata()
.getInputChannels();
assertEquals(1, channels.size());
assertEquals("topic:group.0", channels.iterator().next().getRemoteName());
}
@Test
public void oneInputOverrideName() throws Exception {
this.module.setGroup("mine");
this.module.setIndex(2);
BeanDefinitionRegistryUtils.registerInputChannelBeanDefinition("input", this.context);
refresh();
Collection<InputChannelBinding> channels = this.adapter.getChannelsMetadata()
.getInputChannels();
assertEquals(1, channels.size());
assertEquals("mine.1", channels.iterator().next().getRemoteName());
}
@Test
public void twoOutputsWithQueue() throws Exception {
BeanDefinitionRegistryUtils.registerOutputChannelBeanDefinition("output", this.context);
BeanDefinitionRegistryUtils.registerOutputChannelBeanDefinition("output.queue:foo", this.context);
refresh();
Collection<OutputChannelBinding> channels = this.adapter.getChannelsMetadata()
.getOutputChannels();
List<String> names = getChannelNames(channels);
assertEquals(2, channels.size());
assertTrue(names.contains("group.0"));
assertTrue(names.contains("foo.group.0"));
}
private List<String> getChannelNames(Collection<? extends ChannelBinding> channels) {
List<String> list = new ArrayList<String>();
for (ChannelBinding binding : channels) {
list.add(binding.getRemoteName());
}
return list;
}
@Test
public void overrideNaturalOutputChannelName() throws Exception {
this.module.setOutputChannelName("bar");
BeanDefinitionRegistryUtils.registerOutputChannelBeanDefinition("output.queue:foo", this.context);
refresh();
Collection<OutputChannelBinding> channels = this.adapter.getChannelsMetadata()
.getOutputChannels();
assertEquals(1, channels.size());
assertEquals("foo.bar", channels.iterator().next().getRemoteName());
// TODO: fix this. What should it be?
assertEquals("tap:stream:foo.bar.module.0", channels.iterator().next()
.getTapChannelName());
}
@Test
public void overrideNaturalOutputChannelNamedQueueWithTopic() throws Exception {
this.module.setOutputChannelName("queue:bar");
BeanDefinitionRegistryUtils.registerOutputChannelBeanDefinition("output.topic:foo", this.context);
refresh();
Collection<OutputChannelBinding> channels = this.adapter.getChannelsMetadata()
.getOutputChannels();
assertEquals(1, channels.size());
assertEquals("topic:foo.bar", channels.iterator().next().getRemoteName());
assertEquals("tap:stream:foo.bar.module.0", channels.iterator().next()
.getTapChannelName());
}
@Configuration
@Import(ChannelBindingAdapterConfiguration.class)
protected static class Empty {
@Bean
public LocalMessageBus messageBus() {
return new LocalMessageBus();
}
}
}