diff --git a/spring-cloud-task-samples/pom.xml b/spring-cloud-task-samples/pom.xml
index cd0a96c4..21c03d01 100644
--- a/spring-cloud-task-samples/pom.xml
+++ b/spring-cloud-task-samples/pom.xml
@@ -2,14 +2,26 @@
-
- spring-cloud-task-parent
- org.springframework.cloud
- 1.0.0.BUILD-SNAPSHOT
-
+
4.0.0
spring-cloud-task-samples
+ pom
+
+
+ org.springframework.cloud
+ spring-cloud-task-parent
+ 1.0.0.BUILD-SNAPSHOT
+
+
+
+ UTF-8
+ 1.7
+
+
+
+ timestamp
+
@@ -30,5 +42,4 @@
-
diff --git a/spring-cloud-task-samples/timestamp/README.adoc b/spring-cloud-task-samples/timestamp/README.adoc
new file mode 100644
index 00000000..bc428848
--- /dev/null
+++ b/spring-cloud-task-samples/timestamp/README.adoc
@@ -0,0 +1,26 @@
+= Timestamp Job
+
+This is a Spring Cloud Task application that logs a timestamp.
+
+== Requirements:
+
+* Java 7 or Above
+
+== Classes:
+
+* TaskApplication - the Spring Boot Main Application
+* TimestampTask - the module that writes the log entry as Spring Task
+
+== Build:
+
+[source,shell,indent=2]
+----
+$ mvn clean package
+----
+
+== Run:
+
+[source,shell,indent=2]
+----
+$ java -jar target/timestamp-task-1.0.0.BUILD-SNAPSHOT.jar
+----
diff --git a/spring-cloud-task-samples/timestamp/pom.xml b/spring-cloud-task-samples/timestamp/pom.xml
new file mode 100644
index 00000000..80aa6303
--- /dev/null
+++ b/spring-cloud-task-samples/timestamp/pom.xml
@@ -0,0 +1,64 @@
+
+
+
+ 4.0.0
+
+ org.springframework.cloud
+ timestamp-task
+ jar
+ timestamp-task
+ 1.0.0.BUILD-SNAPSHOT
+ Spring Cloud Timestamp Task
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.3.0.RELEASE
+
+
+
+ org.springframework.cloud.task.timestamp.TaskApplication
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.cloud
+ spring-cloud-task-core
+ 1.0.0.BUILD-SNAPSHOT
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+ org.hsqldb
+ hsqldb
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-cloud-task-samples/timestamp/src/main/java/org/springframework/cloud/task/timestamp/TaskApplication.java b/spring-cloud-task-samples/timestamp/src/main/java/org/springframework/cloud/task/timestamp/TaskApplication.java
new file mode 100644
index 00000000..bd2b7309
--- /dev/null
+++ b/spring-cloud-task-samples/timestamp/src/main/java/org/springframework/cloud/task/timestamp/TaskApplication.java
@@ -0,0 +1,67 @@
+/*
+ * 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.task.timestamp;
+
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.task.annotation.EnableTask;
+import org.springframework.cloud.task.annotation.Task;
+import org.springframework.context.annotation.Bean;
+
+/**
+ * Spring Boot Application that has tasks enabled.
+ */
+@SpringBootApplication
+@EnableTask
+@EnableConfigurationProperties({ TimestampTaskProperties.class })
+public class TaskApplication {
+
+ @Bean
+ public TimestampTask timeStampTask() {
+ return new TimestampTask();
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(TaskApplication.class);
+ }
+
+ /**
+ * A commandline runner that prints a timestamp and is annotated with @Task.
+ */
+ @Task("Demo Timestamp Task")
+ public class TimestampTask implements CommandLineRunner {
+ private final org.slf4j.Logger logger = LoggerFactory.getLogger(TimestampTask.class);
+
+ @Autowired
+ private TimestampTaskProperties config;
+
+ @Override
+ public void run(String... strings) throws Exception {
+ DateFormat dateFormat = new SimpleDateFormat(config.getFormat());
+ logger.info(dateFormat.format(new Date()));
+ }
+ }
+}
diff --git a/spring-cloud-task-samples/timestamp/src/main/java/org/springframework/cloud/task/timestamp/TimestampTaskProperties.java b/spring-cloud-task-samples/timestamp/src/main/java/org/springframework/cloud/task/timestamp/TimestampTaskProperties.java
new file mode 100644
index 00000000..a79eef7f
--- /dev/null
+++ b/spring-cloud-task-samples/timestamp/src/main/java/org/springframework/cloud/task/timestamp/TimestampTaskProperties.java
@@ -0,0 +1,41 @@
+/*
+ * 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.task.timestamp;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.util.Assert;
+
+/**
+ * @author Glenn Renfro
+ */
+@ConfigurationProperties
+public class TimestampTaskProperties {
+
+ /**
+ * The timestamp format, "yyyy-MM-dd HH:mm:ss.SSS" by default.
+ */
+ private String format = "yyyy-MM-dd HH:mm:ss.SSS";
+
+ public String getFormat() {
+ Assert.hasText(format, "format must not be empty nor null");
+ return format;
+ }
+
+ public void setFormat(String format) {
+ this.format = format;
+ }
+}
diff --git a/spring-cloud-task-samples/timestamp/src/test/java/org/springframework/cloud/task/timestamp/TaskApplicationTests.java b/spring-cloud-task-samples/timestamp/src/test/java/org/springframework/cloud/task/timestamp/TaskApplicationTests.java
new file mode 100644
index 00000000..09c19e40
--- /dev/null
+++ b/spring-cloud-task-samples/timestamp/src/test/java/org/springframework/cloud/task/timestamp/TaskApplicationTests.java
@@ -0,0 +1,68 @@
+/*
+ * 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.task.timestamp;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.test.OutputCapture;
+
+/**
+ * Verifies that the Task Application outputs the correct task log entries.
+ *
+ * @author Glenn Renfro
+ */
+public class TaskApplicationTests {
+
+ @Rule
+ public OutputCapture outputCapture = new OutputCapture();
+
+ @Test
+ public void testTimeStampApp() throws Exception {
+ final String TEST_DATE_DOTS = ".......";
+ final String CREATE_TASK_MESSAGE = "Creating: TaskExecution{executionId='";
+ final String UPDATE_TASK_MESSAGE = "Updating: TaskExecution{executionId='";
+ String[] args = { "--format=yyyy" + TEST_DATE_DOTS };
+
+ assertEquals(0, SpringApplication.exit(SpringApplication
+ .run(TaskApplication.class, args)));
+
+ String output = this.outputCapture.toString();
+ assertTrue("Unable to find the timestamp: " + output,
+ output.contains(TEST_DATE_DOTS));
+ assertTrue("Test results do not show create task message: " + output,
+ output.contains(CREATE_TASK_MESSAGE));
+ assertTrue("Test results do not show success message: " + output,
+ output.contains(UPDATE_TASK_MESSAGE));
+
+ String taskTitle = "Demo Timestamp Task";
+ Pattern pattern = Pattern.compile(taskTitle);
+ Matcher matcher = pattern.matcher(output);
+ int count = 0;
+ while (matcher.find()) {
+ count++;
+ }
+ assertEquals("The number of task titles did not match expected: ", 2, count);
+ }
+
+}
diff --git a/spring-cloud-task-samples/timestamp/src/test/java/org/springframework/cloud/task/timestamp/TimestampTaskPropertiesTests.java b/spring-cloud-task-samples/timestamp/src/test/java/org/springframework/cloud/task/timestamp/TimestampTaskPropertiesTests.java
new file mode 100644
index 00000000..40b34643
--- /dev/null
+++ b/spring-cloud-task-samples/timestamp/src/test/java/org/springframework/cloud/task/timestamp/TimestampTaskPropertiesTests.java
@@ -0,0 +1,68 @@
+/*
+ * 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.task.timestamp;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.test.EnvironmentTestUtils;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author Glenn Renfro
+ */
+public class TimestampTaskPropertiesTests {
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testEmptyFormat() {
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
+ EnvironmentTestUtils.addEnvironment(context, "format:");
+ context.register(Conf.class);
+ context.refresh();
+ TimestampTaskProperties properties = context.getBean(TimestampTaskProperties.class);
+ properties.getFormat();
+ }
+
+ @Test
+ public void testFormatDefault() {
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
+ context.register(Conf.class);
+ context.refresh();
+ TimestampTaskProperties properties = context.getBean(TimestampTaskProperties.class);
+ assertEquals("result does not match default format.", "yyyy-MM-dd HH:mm:ss.SSS",
+ properties.getFormat());
+ }
+
+ @Test
+ public void testFormatSet() {
+ final String FORMAT = "yyyy";
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
+ context.register(Conf.class);
+ context.refresh();
+ TimestampTaskProperties properties = context.getBean(TimestampTaskProperties.class);
+ properties.setFormat(FORMAT);
+ assertEquals("result does not match established format.", FORMAT,
+ properties.getFormat());
+ }
+
+ @Configuration
+ @EnableConfigurationProperties(TimestampTaskProperties.class)
+ static class Conf {
+ }
+}