Add aggregate builder and sample applications
No need to specify channel names (just spring.cloud.streams.name). Example
app:
@SpringBootApplication
@EnableChannelBinding
public class ExtendedApplication implements AggregateConfigurer {
@Override
public void configure(AggregateBuilder builder) {
builder
.from(TimeSource.class).as("source")
.via(LoggingTransformer.class)
.via(LoggingTransformer.class).profiles("other")
.to(LogSink.class);
}
}
Fixes gh-2
This commit is contained in:
@@ -23,8 +23,9 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.cloud.streams.config.LifecycleConfiguration;
|
||||
import org.springframework.cloud.streams.config.AggregateBuilderConfiguration;
|
||||
import org.springframework.cloud.streams.config.ChannelBindingAdapterConfiguration;
|
||||
import org.springframework.cloud.streams.config.LifecycleConfiguration;
|
||||
import org.springframework.cloud.streams.config.RabbitServiceConfiguration;
|
||||
import org.springframework.cloud.streams.config.RedisServiceConfiguration;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -40,7 +41,8 @@ import org.springframework.context.annotation.Import;
|
||||
@Inherited
|
||||
@Configuration
|
||||
@Import({ RedisServiceConfiguration.class, RabbitServiceConfiguration.class,
|
||||
ChannelBindingAdapterConfiguration.class, LifecycleConfiguration.class })
|
||||
ChannelBindingAdapterConfiguration.class, LifecycleConfiguration.class,
|
||||
AggregateBuilderConfiguration.class })
|
||||
public @interface EnableChannelBinding {
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* 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.aggregate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.streams")
|
||||
public class AggregateBuilder implements ApplicationContextAware {
|
||||
|
||||
public static final String DEFAULT_NAME = "application";
|
||||
|
||||
private ConfigurableApplicationContext parent;
|
||||
|
||||
private int index = 0;
|
||||
|
||||
private String streamName = "stream";
|
||||
|
||||
private HashSet<SinkConfigurer> sinks = new HashSet<SinkConfigurer>();
|
||||
|
||||
public String getName() {
|
||||
return this.streamName;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.streamName = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.parent = (ConfigurableApplicationContext) applicationContext;
|
||||
}
|
||||
|
||||
public void build() {
|
||||
for (SinkConfigurer sink : this.sinks) {
|
||||
sink.build();
|
||||
}
|
||||
}
|
||||
|
||||
public SourceConfigurer from(Class<?> module) {
|
||||
return new SourceConfigurer(module);
|
||||
}
|
||||
|
||||
private String channelName() {
|
||||
return this.streamName + "." + this.index;
|
||||
}
|
||||
|
||||
private String incrementChannelName() {
|
||||
return this.streamName + "." + (this.index++);
|
||||
}
|
||||
|
||||
public class SourceConfigurer {
|
||||
|
||||
private Class<?> module;
|
||||
private String[] names = null;
|
||||
private String[] profiles = null;
|
||||
|
||||
public SourceConfigurer(Class<?> module) {
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
public SourceConfigurer as(String... names) {
|
||||
this.names = names;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SourceConfigurer profiles(String... profiles) {
|
||||
this.profiles = profiles;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SinkConfigurer to(Class<?> sink) {
|
||||
build();
|
||||
return new SinkConfigurer(sink);
|
||||
}
|
||||
|
||||
public ProcessorConfigurer via(Class<?> processor) {
|
||||
build();
|
||||
return new ProcessorConfigurer(processor);
|
||||
}
|
||||
|
||||
private void build() {
|
||||
childContext(this.module).config(this.names).profiles(this.profiles)
|
||||
.output(channelName()).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class SinkConfigurer {
|
||||
|
||||
private Class<?> module;
|
||||
private String[] names = null;
|
||||
private String[] profiles = null;
|
||||
|
||||
public SinkConfigurer profiles(String... profiles) {
|
||||
this.profiles = profiles;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SinkConfigurer(Class<?> module) {
|
||||
AggregateBuilder.this.sinks.add(this);
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
public SinkConfigurer as(String... names) {
|
||||
this.names = names;
|
||||
return this;
|
||||
}
|
||||
|
||||
void build() {
|
||||
childContext(this.module).config(this.names).profiles(this.profiles)
|
||||
.input(channelName()).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class ProcessorConfigurer {
|
||||
|
||||
private Class<?> module;
|
||||
private String[] names = null;
|
||||
private String[] profiles = null;
|
||||
|
||||
public ProcessorConfigurer(Class<?> module) {
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
public ProcessorConfigurer as(String... names) {
|
||||
this.names = names;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProcessorConfigurer profiles(String... profiles) {
|
||||
this.profiles = profiles;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SinkConfigurer to(Class<?> sink) {
|
||||
build();
|
||||
return new SinkConfigurer(sink);
|
||||
}
|
||||
|
||||
public ProcessorConfigurer via(Class<?> processor) {
|
||||
build();
|
||||
return new ProcessorConfigurer(processor);
|
||||
}
|
||||
|
||||
private void build() {
|
||||
childContext(this.module).config(this.names).profiles(this.profiles)
|
||||
.input(incrementChannelName()).output(channelName()).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private ChildContextBuilder childContext(Class<?> type) {
|
||||
return new ChildContextBuilder(new SpringApplicationBuilder(type,
|
||||
SeedConfiguration.class).parent(AggregateBuilder.this.parent)
|
||||
.showBanner(false).web(false)
|
||||
.initializers(new BeanPostProcessorInitializer()));
|
||||
}
|
||||
|
||||
private class ChildContextBuilder {
|
||||
|
||||
private SpringApplicationBuilder builder;
|
||||
private String configName;
|
||||
private String input;
|
||||
private String output;
|
||||
|
||||
public ChildContextBuilder(SpringApplicationBuilder builder) {
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
public ChildContextBuilder profiles(String... profiles) {
|
||||
if (profiles != null) {
|
||||
this.builder.profiles(profiles);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ChildContextBuilder config(String... configs) {
|
||||
if (configs != null) {
|
||||
this.configName = StringUtils.arrayToCommaDelimitedString(configs);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ChildContextBuilder input(String input) {
|
||||
this.input = input;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ChildContextBuilder output(String output) {
|
||||
this.output = output;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void build() {
|
||||
List<String> args = new ArrayList<String>();
|
||||
if (this.configName != null) {
|
||||
args.add("--spring.config.name=" + this.configName);
|
||||
}
|
||||
if (this.input != null) {
|
||||
args.add("--spring.cloud.channels.inputChannelName=" + this.input);
|
||||
}
|
||||
if (this.output != null) {
|
||||
args.add("--spring.cloud.channels.outputChannelName=" + this.output);
|
||||
}
|
||||
this.builder.run(args.toArray(new String[0]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class BeanPostProcessorInitializer implements
|
||||
ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
|
||||
@Override
|
||||
public void initialize(ConfigurableApplicationContext applicationContext) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
protected static class SeedConfiguration {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.aggregate;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public interface AggregateConfigurer {
|
||||
|
||||
void configure(AggregateBuilder builder);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.config;
|
||||
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.cloud.streams.aggregate.AggregateBuilder;
|
||||
import org.springframework.cloud.streams.aggregate.AggregateConfigurer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
public class AggregateBuilderConfiguration implements CommandLineRunner {
|
||||
|
||||
@Autowired
|
||||
private ListableBeanFactory beanFactory;
|
||||
|
||||
@Bean
|
||||
public AggregateBuilder aggregateBuilder() {
|
||||
return new AggregateBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
for (AggregateConfigurer configurer : this.beanFactory.getBeansOfType(AggregateConfigurer.class).values()) {
|
||||
configurer.configure(aggregateBuilder());
|
||||
}
|
||||
aggregateBuilder().build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,6 +32,7 @@ import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||
import org.springframework.cloud.streams.adapter.ChannelBindingAdapter;
|
||||
import org.springframework.cloud.streams.adapter.ChannelLocator;
|
||||
import org.springframework.cloud.streams.adapter.Input;
|
||||
@@ -104,8 +105,7 @@ public class ChannelBindingAdapterConfiguration {
|
||||
|
||||
protected Collection<OutputChannelBinding> getOutputChannels() {
|
||||
Set<OutputChannelBinding> channels = new LinkedHashSet<OutputChannelBinding>();
|
||||
String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
|
||||
this.beanFactory, MessageChannel.class);
|
||||
String[] names = this.beanFactory.getBeanNamesForType(MessageChannel.class);
|
||||
for (String name : names) {
|
||||
if (name.startsWith("output")) {
|
||||
channels.add(new OutputChannelBinding(name));
|
||||
@@ -116,8 +116,7 @@ public class ChannelBindingAdapterConfiguration {
|
||||
|
||||
protected Collection<InputChannelBinding> getInputChannels() {
|
||||
Set<InputChannelBinding> channels = new LinkedHashSet<InputChannelBinding>();
|
||||
String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
|
||||
this.beanFactory, MessageChannel.class);
|
||||
String[] names = this.beanFactory.getBeanNamesForType(MessageChannel.class);
|
||||
for (String name : names) {
|
||||
if (name.startsWith("input")) {
|
||||
channels.add(new InputChannelBinding(name));
|
||||
@@ -174,7 +173,7 @@ public class ChannelBindingAdapterConfiguration {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(ChannelBindingProperties.class)
|
||||
@ConditionalOnMissingBean(value=ChannelBindingProperties.class, search=SearchStrategy.CURRENT)
|
||||
protected static class ModulePropertiesConfiguration {
|
||||
@Bean(name = "spring.cloud.channels.CONFIGURATION_PROPERTIES")
|
||||
public ChannelBindingProperties moduleProperties() {
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.cloud.streams.config;
|
||||
|
||||
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cloud.Cloud;
|
||||
import org.springframework.cloud.CloudFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -35,6 +36,7 @@ import org.springframework.xd.dirt.integration.rabbit.RabbitMessageBus;
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(RabbitMessageBus.class)
|
||||
@ConditionalOnMissingBean(RabbitMessageBus.class)
|
||||
@ImportResource({ "classpath*:/META-INF/spring-xd/bus/rabbit-bus.xml",
|
||||
"classpath*:/META-INF/spring-xd/analytics/rabbit-analytics.xml" })
|
||||
@PropertySource("classpath:/META-INF/spring-cloud-streams/rabbit-bus.properties")
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.cloud.streams.config;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cloud.Cloud;
|
||||
import org.springframework.cloud.CloudFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -35,6 +36,7 @@ import org.springframework.xd.dirt.integration.redis.RedisMessageBus;
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(RedisMessageBus.class)
|
||||
@ConditionalOnMissingBean(RedisMessageBus.class)
|
||||
@ImportResource({ "classpath*:/META-INF/spring-xd/bus/redis-bus.xml",
|
||||
"classpath*:/META-INF/spring-xd/analytics/redis-analytics.xml" })
|
||||
@PropertySource("classpath:/META-INF/spring-cloud-streams/redis-bus.properties")
|
||||
|
||||
@@ -25,6 +25,8 @@ 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;
|
||||
@@ -129,6 +131,7 @@ ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(value=ModuleProperties.class, search=SearchStrategy.CURRENT)
|
||||
protected static class ModulePropertiesConfiguration {
|
||||
@Bean(name = "spring.cloud.channels.CONFIGURATION_PROPERTIES")
|
||||
public ModuleProperties moduleProperties() {
|
||||
|
||||
69
vanilla-samples/double/pom.xml
Normal file
69
vanilla-samples/double/pom.xml
Normal file
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-streams-sample-double</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>spring-cloud-streams-sample-double</name>
|
||||
<description>Demo project for Spring XD module</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-streams-samples</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<start-class>demo.SinkApplication</start-class>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-streams</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.xd</groupId>
|
||||
<artifactId>spring-xd-messagebus-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-lattice-connector</artifactId>
|
||||
<version>1.0.2.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<classifier>exec</classifier>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -33,9 +33,9 @@ import org.springframework.messaging.MessageChannel;
|
||||
@Configuration
|
||||
@EnableChannelBinding
|
||||
@MessageEndpoint
|
||||
public class ModuleDefinition {
|
||||
public class SinkModuleDefinition {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(ModuleDefinition.class);
|
||||
private static Logger logger = LoggerFactory.getLogger(SinkModuleDefinition.class);
|
||||
|
||||
@Bean
|
||||
public MessageChannel input() {
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 config;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.streams.EnableChannelBinding;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.integration.annotation.InboundChannelAdapter;
|
||||
import org.springframework.integration.annotation.Poller;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.core.MessageSource;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableChannelBinding
|
||||
public class SourceModuleDefinition {
|
||||
|
||||
@Value("${format:YYYY/MM/dd hh:mm:ss}")
|
||||
private String format;
|
||||
|
||||
@Bean
|
||||
public MessageChannel output() {
|
||||
return new DirectChannel();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@InboundChannelAdapter(value = "output", autoStartup = "false", poller = @Poller(fixedDelay = "${fixedDelay}", maxMessagesPerPoll = "1"))
|
||||
public MessageSource<String> timerMessageSource() {
|
||||
return () -> new GenericMessage<>(new SimpleDateFormat(this.format).format(new Date()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package demo;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.streams.EnableChannelBinding;
|
||||
import org.springframework.cloud.streams.aggregate.AggregateBuilder;
|
||||
import org.springframework.cloud.streams.aggregate.AggregateConfigurer;
|
||||
|
||||
import config.SinkModuleDefinition;
|
||||
import config.SourceModuleDefinition;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableChannelBinding
|
||||
public class DoubleApplication implements AggregateConfigurer {
|
||||
|
||||
@Override
|
||||
public void configure(AggregateBuilder builder) {
|
||||
builder.from(SourceModuleDefinition.class).as("source")
|
||||
.to(SinkModuleDefinition.class).as("sink");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
SpringApplication.run(DoubleApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
5
vanilla-samples/double/src/main/resources/sink.yml
Normal file
5
vanilla-samples/double/src/main/resources/sink.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
spring:
|
||||
cloud:
|
||||
channels:
|
||||
inputChannelName: testtock
|
||||
|
||||
6
vanilla-samples/double/src/main/resources/source.yml
Normal file
6
vanilla-samples/double/src/main/resources/source.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
fixedDelay: 5000
|
||||
spring:
|
||||
cloud:
|
||||
channels:
|
||||
outputChannelName: testtock
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package demo;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = DoubleApplication.class)
|
||||
@WebAppConfiguration
|
||||
@DirtiesContext
|
||||
public class ModuleApplicationTests {
|
||||
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
||||
81
vanilla-samples/extended/pom.xml
Normal file
81
vanilla-samples/extended/pom.xml
Normal file
@@ -0,0 +1,81 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-streams-sample-extended</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>spring-cloud-streams-sample-extended</name>
|
||||
<description>Demo project for Spring XD module</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-streams-samples</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<start-class>demo.SinkApplication</start-class>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-streams</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-streams-sample-source</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-streams-sample-transform</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-streams-sample-sink</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.xd</groupId>
|
||||
<artifactId>spring-xd-messagebus-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-lattice-connector</artifactId>
|
||||
<version>1.0.2.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<classifier>exec</classifier>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,32 @@
|
||||
package extended;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.streams.EnableChannelBinding;
|
||||
import org.springframework.cloud.streams.aggregate.AggregateBuilder;
|
||||
import org.springframework.cloud.streams.aggregate.AggregateConfigurer;
|
||||
|
||||
import sink.LogSink;
|
||||
import source.TimeSource;
|
||||
import transform.LoggingTransformer;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableChannelBinding
|
||||
public class ExtendedApplication implements AggregateConfigurer {
|
||||
|
||||
@Override
|
||||
public void configure(AggregateBuilder builder) {
|
||||
// @formatter:off
|
||||
builder
|
||||
.from(TimeSource.class).as("source")
|
||||
.via(LoggingTransformer.class)
|
||||
.via(LoggingTransformer.class).profiles("other")
|
||||
.to(LogSink.class);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
SpringApplication.run(ExtendedApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
spring:
|
||||
profiles: other
|
||||
module:
|
||||
logging:
|
||||
name: other
|
||||
1
vanilla-samples/extended/src/main/resources/source.yml
Normal file
1
vanilla-samples/extended/src/main/resources/source.yml
Normal file
@@ -0,0 +1 @@
|
||||
fixedDelay: 5000
|
||||
@@ -0,0 +1,22 @@
|
||||
package demo;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import extended.ExtendedApplication;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = ExtendedApplication.class)
|
||||
@WebAppConfiguration
|
||||
@DirtiesContext
|
||||
public class ModuleApplicationTests {
|
||||
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,7 +18,29 @@
|
||||
<modules>
|
||||
<module>source</module>
|
||||
<module>sink</module>
|
||||
<module>transform</module>
|
||||
<module>double</module>
|
||||
<module>extended</module>
|
||||
</modules>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-streams-sample-source</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-streams-sample-sink</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-streams-sample-transform</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-xd-samples</artifactId>
|
||||
<artifactId>spring-cloud-streams-samples</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
import config.ModuleDefinition;
|
||||
import sink.LogSink;
|
||||
|
||||
@SpringBootApplication
|
||||
@ComponentScan(basePackageClasses=ModuleDefinition.class)
|
||||
@ComponentScan(basePackageClasses=LogSink.class)
|
||||
public class SinkApplication {
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
|
||||
50
vanilla-samples/sink/src/main/java/sink/LogSink.java
Normal file
50
vanilla-samples/sink/src/main/java/sink/LogSink.java
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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 sink;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.cloud.streams.EnableChannelBinding;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.integration.annotation.MessageEndpoint;
|
||||
import org.springframework.integration.annotation.ServiceActivator;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableChannelBinding
|
||||
@MessageEndpoint
|
||||
public class LogSink {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(LogSink.class);
|
||||
|
||||
@Bean
|
||||
public MessageChannel input() {
|
||||
return new DirectChannel();
|
||||
}
|
||||
|
||||
@ServiceActivator(inputChannel="input")
|
||||
public void loggerSink(Object payload) {
|
||||
logger.info("Received: " + payload);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-xd-samples</artifactId>
|
||||
<artifactId>spring-cloud-streams-samples</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
import config.ModuleDefinition;
|
||||
import source.TimeSource;
|
||||
|
||||
@SpringBootApplication
|
||||
@ComponentScan(basePackageClasses=ModuleDefinition.class)
|
||||
@ComponentScan(basePackageClasses=TimeSource.class)
|
||||
public class SourceApplication {
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package config;
|
||||
package source;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
@@ -38,7 +38,7 @@ import org.springframework.messaging.support.GenericMessage;
|
||||
@Configuration
|
||||
@EnableChannelBinding
|
||||
@EnableConfigurationProperties(TimeSourceOptionsMetadata.class)
|
||||
public class ModuleDefinition {
|
||||
public class TimeSource {
|
||||
|
||||
@Autowired
|
||||
private TimeSourceOptionsMetadata options;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package config;
|
||||
package source;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.Pattern;
|
||||
@@ -1,11 +1,21 @@
|
||||
fixedDelay: 5000
|
||||
server:
|
||||
port: 8081
|
||||
spring:
|
||||
cloud:
|
||||
channels:
|
||||
inpoutChannelName: testtock
|
||||
inputChannelName: testtock
|
||||
# uncomment below to use the last digit of the seconds as a partition key
|
||||
# hashcode(key) % N is then applied with N being the partitionCount value
|
||||
# thus, even seconds should go to the 0 queue, odd seconds to the 1 queue
|
||||
#producerProperties:
|
||||
# partitionKeyExpression: payload.charAt(payload.length()-1)
|
||||
# partitionCount: 2
|
||||
|
||||
---
|
||||
spring:
|
||||
profiles: extended
|
||||
spring:
|
||||
cloud:
|
||||
channels:
|
||||
inputChannelName: xformed
|
||||
|
||||
69
vanilla-samples/transform/pom.xml
Normal file
69
vanilla-samples/transform/pom.xml
Normal file
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-streams-sample-transform</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>spring-cloud-streams-sample-transform</name>
|
||||
<description>Demo project for Spring XD module</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-streams-samples</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<start-class>demo.SinkApplication</start-class>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-streams</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.xd</groupId>
|
||||
<artifactId>spring-xd-messagebus-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-lattice-connector</artifactId>
|
||||
<version>1.0.2.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<classifier>exec</classifier>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,17 @@
|
||||
package demo;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
import transform.LoggingTransformer;
|
||||
|
||||
@SpringBootApplication
|
||||
@ComponentScan(basePackageClasses=LoggingTransformer.class)
|
||||
public class TransformApplication {
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
SpringApplication.run(TransformApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 transform;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.streams.EnableChannelBinding;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.integration.annotation.MessageEndpoint;
|
||||
import org.springframework.integration.annotation.ServiceActivator;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.SubscribableChannel;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableChannelBinding
|
||||
@MessageEndpoint
|
||||
@ConfigurationProperties("module.logging")
|
||||
public class LoggingTransformer {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(LoggingTransformer.class);
|
||||
|
||||
/**
|
||||
* The name to include in the log message
|
||||
*/
|
||||
private String name = "logging";
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MessageChannel input() {
|
||||
return new DirectChannel();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SubscribableChannel output() {
|
||||
return new DirectChannel();
|
||||
}
|
||||
|
||||
@ServiceActivator(inputChannel = "input", outputChannel = "output")
|
||||
public Object transform(Object payload) {
|
||||
logger.info("Transformed by " + this.name + ": " + payload);
|
||||
return payload;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
server:
|
||||
port: 8082
|
||||
spring:
|
||||
cloud:
|
||||
channels:
|
||||
outputChannelName: xformed
|
||||
inputChannelName: testtock
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package demo;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = TransformApplication.class)
|
||||
@WebAppConfiguration
|
||||
@DirtiesContext
|
||||
public class ModuleApplicationTests {
|
||||
|
||||
@Test
|
||||
public void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user