diff --git a/pom.xml b/pom.xml
index 179e32e14..97aab6549 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,12 +10,13 @@
Pivotal Software, Inc.
http://www.spring.io
-
- 1.7
- 1.3.0.BUILD-SNAPSHOT
- Brixton.BUILD-SNAPSHOT
- 2.0.0.BUILD-SNAPSHOT
-
+
+ 1.7
+ 1.3.0.BUILD-SNAPSHOT
+ Brixton.BUILD-SNAPSHOT
+ 2.0.0.BUILD-SNAPSHOT
+ 4.2.0.RC2
+
spring-cloud-streams
spring-xd-runner
@@ -47,75 +48,36 @@
spring-xd-runner
1.0.0.BUILD-SNAPSHOT
-
- org.springframework.xd
- spring-xd-dirt
- ${spring-xd.version}
-
-
- jackson-core-asl
- org.codehaus.jackson
-
-
- org.springframework.xd
- spring-xd-spark-streaming
-
-
- org.springframework.xd
- spring-xd-hadoop
-
-
- org.springframework.xd
- spring-xd-batch
-
-
- org.springframework.xd
- spring-xd-ui
-
-
- slf4j-log4j12
- org.slf4j
-
-
- zookeeper
- org.apache.zookeeper
-
-
- spring-boot-starter-security
- org.springframework.boot
-
-
- spring-security-ldap
- org.springframework.security
-
-
- spring-jdbc
- org.springframework
-
-
- spring-batch-integration
- org.springframework.batch
-
-
- spring-batch-admin-manager
- org.springframework.batch
-
-
- spring-data-mongodb
- org.springframework.data
-
-
-
-
- org.springframework.xd
- spring-xd-messagebus-redis
- ${spring-xd.version}
-
-
- org.springframework.xd
- spring-xd-messagebus-rabbit
- ${spring-xd.version}
-
+
+ org.springframework.xd
+ spring-xd-codec
+ ${spring-xd.version}
+
+
+ org.springframework.xd
+ spring-xd-module
+ ${spring-xd.version}
+
+
+ org.springframework.xd
+ spring-xd-messagebus-local
+ ${spring-xd.version}
+
+
+ org.springframework.xd
+ spring-xd-messagebus-redis
+ ${spring-xd.version}
+
+
+ org.springframework.xd
+ spring-xd-messagebus-rabbit
+ ${spring-xd.version}
+
+
+ org.springframework
+ spring-messaging
+ ${spring-framework.version}
+
diff --git a/spring-cloud-streams/pom.xml b/spring-cloud-streams/pom.xml
index 6522e62f7..a24391b03 100644
--- a/spring-cloud-streams/pom.xml
+++ b/spring-cloud-streams/pom.xml
@@ -31,11 +31,34 @@
org.springframework.boot
spring-boot-starter-web
+
+
+ org.springframework
+ spring-messaging
+
+
+
+ org.springframework.cloud
+ spring-cloud-core
+
+
org.springframework.xd
- spring-xd-dirt
+ spring-xd-codec
+
+ org.springframework.xd
+ spring-xd-module
+
+
+
+ org.springframework.xd
+ spring-xd-messagebus-local
+
+
+
+
org.springframework.xd
spring-xd-messagebus-redis
diff --git a/spring-cloud-streams/src/main/java/org/springframework/cloud/streams/config/ChannelBindingAdapterConfiguration.java b/spring-cloud-streams/src/main/java/org/springframework/cloud/streams/config/ChannelBindingAdapterConfiguration.java
index 1f34d235d..1209cb7b8 100644
--- a/spring-cloud-streams/src/main/java/org/springframework/cloud/streams/config/ChannelBindingAdapterConfiguration.java
+++ b/spring-cloud-streams/src/main/java/org/springframework/cloud/streams/config/ChannelBindingAdapterConfiguration.java
@@ -49,7 +49,7 @@ import org.springframework.xd.dirt.integration.bus.MessageBusAwareRouterBeanPost
*
*/
@Configuration
-@ImportResource("classpath*:/META-INF/spring-xd/bus/codec.xml")
+@ImportResource("classpath*:/META-INF/spring-bus/codec.xml")
public class ChannelBindingAdapterConfiguration {
@Autowired
diff --git a/spring-cloud-streams/src/main/java/org/springframework/xd/dirt/integration/bus/MessageBusAwareChannelResolver.java b/spring-cloud-streams/src/main/java/org/springframework/xd/dirt/integration/bus/MessageBusAwareChannelResolver.java
new file mode 100644
index 000000000..6a5f72551
--- /dev/null
+++ b/spring-cloud-streams/src/main/java/org/springframework/xd/dirt/integration/bus/MessageBusAwareChannelResolver.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2013-2014 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.integration.bus;
+
+import java.util.Properties;
+
+import org.springframework.messaging.MessageChannel;
+import org.springframework.messaging.core.BeanFactoryMessageChannelDestinationResolver;
+import org.springframework.messaging.core.DestinationResolutionException;
+
+/**
+ * A {@link org.springframework.messaging.core.DestinationResolver} implementation that first checks for any channel
+ * whose name begins with a colon in the {@link MessageBus}.
+ *
+ * @author Mark Fisher
+ * @author Gary Russell
+ */
+public class MessageBusAwareChannelResolver extends BeanFactoryMessageChannelDestinationResolver {
+
+ private final MessageBus messageBus;
+
+ private final Properties producerProperties;
+
+ public MessageBusAwareChannelResolver(MessageBus messageBus, Properties producerProperties) {
+ this.messageBus = messageBus;
+ this.producerProperties = producerProperties;
+ }
+
+ @Override
+ public MessageChannel resolveDestination(String name) {
+ MessageChannel channel = null;
+ try {
+ return super.resolveDestination(name);
+ }
+ catch (DestinationResolutionException e) {
+ }
+ if (name.indexOf(":") != -1) {
+ if (messageBus != null) {
+ String[] tokens = name.split(":", 2);
+ String type = tokens[0];
+ if ("queue".equals(type)) {
+ channel = this.messageBus.bindDynamicProducer(name, this.producerProperties);
+ }
+ else if ("topic".equals(type)) {
+ channel = this.messageBus.bindDynamicPubSubProducer(name, this.producerProperties);
+ }
+ else {
+ throw new IllegalArgumentException("unrecognized channel type: " + type);
+ }
+ }
+ }
+ if (channel == null) {
+ channel = super.resolveDestination(name);
+ }
+ return channel;
+ }
+
+}
diff --git a/spring-cloud-streams/src/main/java/org/springframework/xd/dirt/integration/bus/MessageBusAwareRouterBeanPostProcessor.java b/spring-cloud-streams/src/main/java/org/springframework/xd/dirt/integration/bus/MessageBusAwareRouterBeanPostProcessor.java
new file mode 100644
index 000000000..535e745b9
--- /dev/null
+++ b/spring-cloud-streams/src/main/java/org/springframework/xd/dirt/integration/bus/MessageBusAwareRouterBeanPostProcessor.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2013-2014 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.integration.bus;
+
+import java.util.Properties;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.integration.router.AbstractMappingMessageRouter;
+
+/**
+ * A {@link BeanPostProcessor} that sets a {@link MessageBusAwareChannelResolver} on any bean of type
+ * {@link AbstractMappingMessageRouter} within the context.
+ *
+ * @author Mark Fisher
+ * @author Gary Russell
+ */
+public class MessageBusAwareRouterBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
+
+ private final MessageBusAwareChannelResolver channelResolver;
+
+ public MessageBusAwareRouterBeanPostProcessor(MessageBus messageBus, Properties producerProperties) {
+ this.channelResolver = new MessageBusAwareChannelResolver(messageBus, producerProperties);
+ }
+
+ @Override
+ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
+ channelResolver.setBeanFactory(beanFactory);
+ }
+
+ @Override
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+ return bean;
+ }
+
+ @Override
+ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+ if (bean instanceof AbstractMappingMessageRouter) {
+ ((AbstractMappingMessageRouter) bean).setChannelResolver(channelResolver);
+ }
+ return bean;
+ }
+
+}
diff --git a/spring-cloud-streams/src/main/resources/META-INF/spring-bus/codec.xml b/spring-cloud-streams/src/main/resources/META-INF/spring-bus/codec.xml
new file mode 100644
index 000000000..f88e4255d
--- /dev/null
+++ b/spring-cloud-streams/src/main/resources/META-INF/spring-bus/codec.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-xd-runner/pom.xml b/spring-xd-runner/pom.xml
index 0a506f930..61afd2558 100644
--- a/spring-xd-runner/pom.xml
+++ b/spring-xd-runner/pom.xml
@@ -33,7 +33,12 @@
org.springframework.xd
- spring-xd-dirt
+ spring-xd-codec
+
+
+
+ org.springframework.xd
+ spring-xd-module
diff --git a/spring-xd-runner/src/main/java/org/springframework/cloud/streams/xd/ModuleOptionsPropertySourceInitializer.java b/spring-xd-runner/src/main/java/org/springframework/cloud/streams/xd/ModuleOptionsPropertySourceInitializer.java
index 519d670bf..81b5a9b17 100644
--- a/spring-xd-runner/src/main/java/org/springframework/cloud/streams/xd/ModuleOptionsPropertySourceInitializer.java
+++ b/spring-xd-runner/src/main/java/org/springframework/cloud/streams/xd/ModuleOptionsPropertySourceInitializer.java
@@ -35,7 +35,6 @@ 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.job.JobPluginMetadataResolver;
import org.springframework.xd.dirt.plugins.stream.ModuleTypeConversionPluginMetadataResolver;
import org.springframework.xd.module.ModuleDefinition;
import org.springframework.xd.module.ModuleDefinitions;
@@ -104,7 +103,6 @@ ApplicationContextInitializer {
List delegates = new ArrayList();
delegates.add(defaultResolver());
delegates.add(new ModuleTypeConversionPluginMetadataResolver());
- delegates.add(new JobPluginMetadataResolver());
DelegatingModuleOptionsMetadataResolver delegatingResolver = new DelegatingModuleOptionsMetadataResolver();
delegatingResolver.setDelegates(delegates);
ModuleOptionsMetadataResolver resolver = delegatingResolver;
diff --git a/spring-xd-runner/src/main/java/org/springframework/xd/dirt/plugins/stream/CustomMimeTypeConverter.java b/spring-xd-runner/src/main/java/org/springframework/xd/dirt/plugins/stream/CustomMimeTypeConverter.java
new file mode 100644
index 000000000..ed5bebed8
--- /dev/null
+++ b/spring-xd-runner/src/main/java/org/springframework/xd/dirt/plugins/stream/CustomMimeTypeConverter.java
@@ -0,0 +1,41 @@
+/*
+ * 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 {
+
+ @Override
+ public MimeType convert(String source) {
+ if (!source.contains("/")) {
+ return MimeType.valueOf("application/x-java-object;type=" + source);
+ }
+ return MimeType.valueOf(source);
+ }
+
+}
diff --git a/spring-xd-runner/src/main/java/org/springframework/xd/dirt/plugins/stream/ModuleTypeConversionPluginMetadataResolver.java b/spring-xd-runner/src/main/java/org/springframework/xd/dirt/plugins/stream/ModuleTypeConversionPluginMetadataResolver.java
new file mode 100644
index 000000000..c5134c80b
--- /dev/null
+++ b/spring-xd-runner/src/main/java/org/springframework/xd/dirt/plugins/stream/ModuleTypeConversionPluginMetadataResolver.java
@@ -0,0 +1,117 @@
+/*
+ * 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 moms = new ArrayList();
+ 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;
+ }
+
+ }
+
+}
diff --git a/spring-xd-samples/sink/pom.xml b/spring-xd-samples/sink/pom.xml
index 50a265857..0866ed098 100644
--- a/spring-xd-samples/sink/pom.xml
+++ b/spring-xd-samples/sink/pom.xml
@@ -37,6 +37,10 @@
spring-cloud-lattice-connector
1.0.2.BUILD-SNAPSHOT
+
+ org.springframework.boot
+ spring-boot-starter-redis
+
org.springframework.boot
spring-boot-configuration-processor
diff --git a/spring-xd-samples/sink/src/main/java/org/springframework/xd/dirt/modules/metadata/LogSinkOptionsMetadata.java b/spring-xd-samples/sink/src/main/java/org/springframework/xd/dirt/modules/metadata/LogSinkOptionsMetadata.java
new file mode 100644
index 000000000..13b0e2422
--- /dev/null
+++ b/spring-xd-samples/sink/src/main/java/org/springframework/xd/dirt/modules/metadata/LogSinkOptionsMetadata.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2014 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.modules.metadata;
+
+import org.hibernate.validator.constraints.NotBlank;
+
+import org.springframework.xd.module.options.spi.ModuleOption;
+import org.springframework.xd.module.options.spi.ModulePlaceholders;
+
+
+/**
+ * Captures options for the {@code log} sink module.
+ *
+ * @author Eric Bottard
+ * @author Gary Russell
+ */
+public class LogSinkOptionsMetadata {
+
+ private String name = ModulePlaceholders.XD_STREAM_NAME;
+
+ private String expression = "payload";
+
+ private String level = "INFO";
+
+ @NotBlank
+ public String getName() {
+ return name;
+ }
+
+ @ModuleOption("the name of the log category to log to (will be prefixed by 'xd.sink.')")
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @NotBlank
+ public String getExpression() {
+ return expression;
+ }
+
+ @ModuleOption("the expression to be evaluated for the log content; use '#root' to log the full message")
+ public void setExpression(String expression) {
+ this.expression = expression;
+ }
+
+ @NotBlank
+ public String getLevel() {
+ return level;
+ }
+
+ @ModuleOption("the log level")
+ public void setLevel(String level) {
+ this.level = level.toUpperCase();
+ }
+
+}
diff --git a/spring-xd-samples/source-xml/pom.xml b/spring-xd-samples/source-xml/pom.xml
index a4fcadc42..3ad9e1364 100644
--- a/spring-xd-samples/source-xml/pom.xml
+++ b/spring-xd-samples/source-xml/pom.xml
@@ -37,6 +37,10 @@
spring-boot-configuration-processor
true
+
+ org.springframework.boot
+ spring-boot-starter-redis
+
org.springframework.boot
spring-boot-starter-test
diff --git a/spring-xd-samples/source-xml/src/main/java/org/springframework/xd/dirt/modules/metadata/TimeSourceOptionsMetadata.java b/spring-xd-samples/source-xml/src/main/java/org/springframework/xd/dirt/modules/metadata/TimeSourceOptionsMetadata.java
new file mode 100644
index 000000000..6dc884938
--- /dev/null
+++ b/spring-xd-samples/source-xml/src/main/java/org/springframework/xd/dirt/modules/metadata/TimeSourceOptionsMetadata.java
@@ -0,0 +1,61 @@
+/*
+ * 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.xd.dirt.modules.metadata;
+
+import org.springframework.xd.module.options.mixins.MaxMessagesDefaultOneMixin;
+import org.springframework.xd.module.options.mixins.PeriodicTriggerMixin;
+import org.springframework.xd.module.options.spi.Mixin;
+import org.springframework.xd.module.options.spi.ModuleOption;
+import org.springframework.xd.module.options.validation.DateFormat;
+
+/**
+ * Describes options to the {@code time} source module.
+ *
+ * @author Eric Bottard
+ * @author Gary Russell
+ */
+@Mixin({ PeriodicTriggerMixin.class, MaxMessagesDefaultOneMixin.class })
+public class TimeSourceOptionsMetadata {
+
+ private String format = "yyyy-MM-dd HH:mm:ss";
+
+ private int fixedDelay = 1;
+
+
+ @DateFormat
+ public String getFormat() {
+ return format;
+ }
+
+ @ModuleOption("how to render the current time, using SimpleDateFormat")
+ public void setFormat(String format) {
+ this.format = format;
+ }
+
+
+ public int getFixedDelay() {
+ return fixedDelay;
+ }
+
+
+ @ModuleOption("time delay between messages, expressed in TimeUnits (seconds by default)")
+ public void setFixedDelay(int fixedDelay) {
+ this.fixedDelay = fixedDelay;
+ }
+
+
+}
diff --git a/spring-xd-samples/source/pom.xml b/spring-xd-samples/source/pom.xml
index 32b1aca41..0a7397136 100644
--- a/spring-xd-samples/source/pom.xml
+++ b/spring-xd-samples/source/pom.xml
@@ -42,6 +42,10 @@
spring-boot-configuration-processor
true
+
+ org.springframework.boot
+ spring-boot-starter-redis
+
org.springframework.boot
spring-boot-starter-test
diff --git a/spring-xd-samples/source/src/main/java/org/springframework/xd/dirt/modules/metadata/TimeSourceOptionsMetadata.java b/spring-xd-samples/source/src/main/java/org/springframework/xd/dirt/modules/metadata/TimeSourceOptionsMetadata.java
new file mode 100644
index 000000000..6dc884938
--- /dev/null
+++ b/spring-xd-samples/source/src/main/java/org/springframework/xd/dirt/modules/metadata/TimeSourceOptionsMetadata.java
@@ -0,0 +1,61 @@
+/*
+ * 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.xd.dirt.modules.metadata;
+
+import org.springframework.xd.module.options.mixins.MaxMessagesDefaultOneMixin;
+import org.springframework.xd.module.options.mixins.PeriodicTriggerMixin;
+import org.springframework.xd.module.options.spi.Mixin;
+import org.springframework.xd.module.options.spi.ModuleOption;
+import org.springframework.xd.module.options.validation.DateFormat;
+
+/**
+ * Describes options to the {@code time} source module.
+ *
+ * @author Eric Bottard
+ * @author Gary Russell
+ */
+@Mixin({ PeriodicTriggerMixin.class, MaxMessagesDefaultOneMixin.class })
+public class TimeSourceOptionsMetadata {
+
+ private String format = "yyyy-MM-dd HH:mm:ss";
+
+ private int fixedDelay = 1;
+
+
+ @DateFormat
+ public String getFormat() {
+ return format;
+ }
+
+ @ModuleOption("how to render the current time, using SimpleDateFormat")
+ public void setFormat(String format) {
+ this.format = format;
+ }
+
+
+ public int getFixedDelay() {
+ return fixedDelay;
+ }
+
+
+ @ModuleOption("time delay between messages, expressed in TimeUnits (seconds by default)")
+ public void setFixedDelay(int fixedDelay) {
+ this.fixedDelay = fixedDelay;
+ }
+
+
+}
diff --git a/spring-xd-samples/tap/pom.xml b/spring-xd-samples/tap/pom.xml
index 8fe8dcffe..824529fbb 100644
--- a/spring-xd-samples/tap/pom.xml
+++ b/spring-xd-samples/tap/pom.xml
@@ -37,6 +37,10 @@
spring-boot-configuration-processor
true
+
+ org.springframework.boot
+ spring-boot-starter-redis
+
org.springframework.boot
spring-boot-starter-test