diff --git a/spring-cloud-task-docs/src/main/asciidoc/stream.adoc b/spring-cloud-task-docs/src/main/asciidoc/stream.adoc index 2c0e8f85..f386b506 100644 --- a/spring-cloud-task-docs/src/main/asciidoc/stream.adoc +++ b/spring-cloud-task-docs/src/main/asciidoc/stream.adoc @@ -13,8 +13,18 @@ covers the integration options for Spring Cloud Task and Spring Cloud Stream. Allows a user to launch tasks from a stream. This is done by creating a sink that listens for a message that contains a `TaskLaunchRequest` as its payload. The -TaskLaunchRequest contains the maven coordinates to the Task that is to be executed. It -also has a Map that contains the environment variables that will be used by the Task. +TaskLaunchRequest contains: + +* uri - to the task artifact that is to be executed. +* applicationName - the name that will be associated with the task. If no +applicationName is set the TaskLaunchRequest will generate a task name +comprised of the following: `Task-` +* commandLineArguments - a list containing the command line arguments for the +task. +* environmentProperties - a map containing the environment variables to be used +by the task +* deploymentProperties - a map containing the properties that will be used by +the deployer to deploy the task. NOTE: If the payload is of a different type then the sink will throw an exception. diff --git a/spring-cloud-task-integration-tests/src/test/java/org/springframework/cloud/task/launcher/TaskLauncherSinkTests.java b/spring-cloud-task-integration-tests/src/test/java/org/springframework/cloud/task/launcher/TaskLauncherSinkTests.java index 5bf2d988..0511b30e 100644 --- a/spring-cloud-task-integration-tests/src/test/java/org/springframework/cloud/task/launcher/TaskLauncherSinkTests.java +++ b/spring-cloud-task-integration-tests/src/test/java/org/springframework/cloud/task/launcher/TaskLauncherSinkTests.java @@ -62,7 +62,7 @@ import static org.junit.Assert.assertTrue; public class TaskLauncherSinkTests { private final static int WAIT_INTERVAL = 500; - private final static int MAX_WAIT_TIME = 5000; + private final static int MAX_WAIT_TIME = 10000; private final static String URL = "maven://io.spring.cloud:" + "timestamp-task:jar:1.1.0.M2"; private final static String DATASOURCE_URL; @@ -169,7 +169,8 @@ public class TaskLauncherSinkTests { } private void launchTask(String artifactURL) { - TaskLaunchRequest request = new TaskLaunchRequest(artifactURL, null, this.properties, null); + TaskLaunchRequest request = new TaskLaunchRequest(artifactURL, null, + this.properties, null, null); GenericMessage message = new GenericMessage<>(request); this.sink.input().send(message); } diff --git a/spring-cloud-task-samples/taskprocessor/src/main/java/io/spring/TaskProcessor.java b/spring-cloud-task-samples/taskprocessor/src/main/java/io/spring/TaskProcessor.java index c712ecc8..50221159 100644 --- a/spring-cloud-task-samples/taskprocessor/src/main/java/io/spring/TaskProcessor.java +++ b/spring-cloud-task-samples/taskprocessor/src/main/java/io/spring/TaskProcessor.java @@ -58,7 +58,9 @@ public class TaskProcessor { } properties.put("payload", message); - TaskLaunchRequest request = new TaskLaunchRequest(processorProperties.getUri(), null, properties, null); + TaskLaunchRequest request = new TaskLaunchRequest( + processorProperties.getUri(), null, properties, null, + processorProperties.getApplicationName()); return new GenericMessage(request); } diff --git a/spring-cloud-task-samples/taskprocessor/src/main/java/io/spring/TaskProcessorProperties.java b/spring-cloud-task-samples/taskprocessor/src/main/java/io/spring/TaskProcessorProperties.java index a0fb8bb0..d3618cd0 100644 --- a/spring-cloud-task-samples/taskprocessor/src/main/java/io/spring/TaskProcessorProperties.java +++ b/spring-cloud-task-samples/taskprocessor/src/main/java/io/spring/TaskProcessorProperties.java @@ -38,6 +38,8 @@ public class TaskProcessorProperties { private String dataSourcePassword; + private String applicationName; + public String getDataSourceUrl() { @@ -79,4 +81,12 @@ public class TaskProcessorProperties { public void setUri(String uri) { this.uri = uri; } + + public String getApplicationName() { + return applicationName; + } + + public void setApplicationName(String applicationName) { + this.applicationName = applicationName; + } } diff --git a/spring-cloud-task-samples/taskprocessor/src/test/java/io/spring/TaskProcessorApplicationTests.java b/spring-cloud-task-samples/taskprocessor/src/test/java/io/spring/TaskProcessorApplicationTests.java index 40cc343d..61131409 100644 --- a/spring-cloud-task-samples/taskprocessor/src/test/java/io/spring/TaskProcessorApplicationTests.java +++ b/spring-cloud-task-samples/taskprocessor/src/test/java/io/spring/TaskProcessorApplicationTests.java @@ -58,8 +58,10 @@ public class TaskProcessorApplicationTests { channels.input().send(new GenericMessage(DEFAULT_PAYLOAD)); Map properties = new HashMap(); properties.put("payload", DEFAULT_PAYLOAD); - TaskLaunchRequest expectedRequest = new TaskLaunchRequest("maven://org.springframework.cloud.task.app:" - + "timestamp-task:jar:1.0.1.RELEASE", null, properties, null); + TaskLaunchRequest expectedRequest = new TaskLaunchRequest( + "maven://org.springframework.cloud.task.app:" + + "timestamp-task:jar:1.0.1.RELEASE", null, properties, + null, null); assertThat(collector.forChannel(channels.output()), receivesPayloadThat(is(expectedRequest))); } diff --git a/spring-cloud-task-samples/tasksink/src/test/java/io/spring/TaskSinkApplicationTests.java b/spring-cloud-task-samples/tasksink/src/test/java/io/spring/TaskSinkApplicationTests.java index 5c00f55d..06f52a0e 100644 --- a/spring-cloud-task-samples/tasksink/src/test/java/io/spring/TaskSinkApplicationTests.java +++ b/spring-cloud-task-samples/tasksink/src/test/java/io/spring/TaskSinkApplicationTests.java @@ -62,8 +62,10 @@ public class TaskSinkApplicationTests { Map properties = new HashMap(); properties.put("server.port", "0"); - TaskLaunchRequest request = new TaskLaunchRequest("maven://org.springframework.cloud.task.app:" - + "timestamp-task:jar:1.0.1.RELEASE", null, properties, null); + TaskLaunchRequest request = new TaskLaunchRequest( + "maven://org.springframework.cloud.task.app:" + + "timestamp-task:jar:1.0.1.RELEASE", null, properties, + null, null); GenericMessage message = new GenericMessage(request); this.sink.input().send(message); assertEquals(LaunchState.complete, testTaskLauncher.status("TESTSTATUS").getState()); diff --git a/spring-cloud-task-stream/src/main/java/org/springframework/cloud/task/launcher/TaskLaunchRequest.java b/spring-cloud-task-stream/src/main/java/org/springframework/cloud/task/launcher/TaskLaunchRequest.java index ca7a4721..8afb52e1 100644 --- a/spring-cloud-task-stream/src/main/java/org/springframework/cloud/task/launcher/TaskLaunchRequest.java +++ b/spring-cloud-task-stream/src/main/java/org/springframework/cloud/task/launcher/TaskLaunchRequest.java @@ -23,8 +23,10 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * Request that contains the maven repository and property information required by the @@ -39,6 +41,7 @@ public class TaskLaunchRequest implements Serializable{ private List commandlineArguments; private Map environmentProperties; private Map deploymentProperties; + private String applicationName; /** * Constructor for the TaskLaunchRequest; @@ -46,16 +49,21 @@ public class TaskLaunchRequest implements Serializable{ * @param commandlineArguments list of commandlineArguments to be used by the task * @param environmentProperties are the environment variables for this task. * @param deploymentProperties are the variables used to setup task on the platform. + * @param applicationName name to be applied to the launched task. If set + * to null then the launched task name will be "Task-. */ public TaskLaunchRequest(String uri, List commandlineArguments, - Map environmentProperties, - Map deploymentProperties) { + Map environmentProperties, + Map deploymentProperties, + String applicationName) { Assert.hasText(uri, "uri must not be empty nor null."); this.uri = uri; this.commandlineArguments = (commandlineArguments == null) ? new ArrayList() : commandlineArguments; this.environmentProperties = environmentProperties == null ? new HashMap() : environmentProperties; this.deploymentProperties = deploymentProperties == null ? new HashMap() : deploymentProperties; + setApplicationName(applicationName); } /** @@ -90,6 +98,26 @@ public class TaskLaunchRequest implements Serializable{ return deploymentProperties; } + /** + * Returns the name that will be associated with the launched task. + * + * @return string containing the application name. + */ + public String getApplicationName() { + return applicationName; + } + + /** + * Sets the name to be applied to the launched task. If set + * to null then the launched task name will be "Task-". + * + * @param applicationName the name to be + */ + public void setApplicationName(String applicationName) { + this.applicationName = !StringUtils.hasText(applicationName) ? "Task-" + + UUID.randomUUID().toString() : applicationName; + } + @Override public String toString() { return "TaskLaunchRequest{" + diff --git a/spring-cloud-task-stream/src/main/java/org/springframework/cloud/task/launcher/TaskLauncherSink.java b/spring-cloud-task-stream/src/main/java/org/springframework/cloud/task/launcher/TaskLauncherSink.java index 490b0911..4a932e25 100644 --- a/spring-cloud-task-stream/src/main/java/org/springframework/cloud/task/launcher/TaskLauncherSink.java +++ b/spring-cloud-task-stream/src/main/java/org/springframework/cloud/task/launcher/TaskLauncherSink.java @@ -62,7 +62,7 @@ public class TaskLauncherSink { Assert.notNull(this.taskLauncher, "TaskLauncher has not been initialized"); logger.info("Launching Task for the following resource " + taskLaunchRequest); Resource resource = this.resourceLoader.getResource(taskLaunchRequest.getUri()); - AppDefinition definition = new AppDefinition("Task-" + taskLaunchRequest.hashCode(), taskLaunchRequest.getEnvironmentProperties()); + AppDefinition definition = new AppDefinition(taskLaunchRequest.getApplicationName(), taskLaunchRequest.getEnvironmentProperties()); AppDeploymentRequest request = new AppDeploymentRequest(definition, resource, taskLaunchRequest.getDeploymentProperties(), taskLaunchRequest.getCommandlineArguments()); this.taskLauncher.launch(request); } diff --git a/spring-cloud-task-stream/src/test/java/org/springframework/cloud/task/launcher/TaskLaunchRequestTests.java b/spring-cloud-task-stream/src/test/java/org/springframework/cloud/task/launcher/TaskLaunchRequestTests.java index dadfdd16..463ece05 100644 --- a/spring-cloud-task-stream/src/test/java/org/springframework/cloud/task/launcher/TaskLaunchRequestTests.java +++ b/spring-cloud-task-stream/src/test/java/org/springframework/cloud/task/launcher/TaskLaunchRequestTests.java @@ -34,6 +34,8 @@ import static org.junit.Assert.assertTrue; public class TaskLaunchRequestTests { public static final String URI = "http://myURI"; + public static final String APP_NAME = "MY_APP_NAME"; + @Test public void testEquals() { List args = new ArrayList<>(); @@ -42,46 +44,50 @@ public class TaskLaunchRequestTests { map.put("bar", "baz"); TaskLaunchRequest request = new TaskLaunchRequest(URI, - Collections.EMPTY_LIST, - Collections.EMPTY_MAP, - Collections.EMPTY_MAP); + Collections.EMPTY_LIST, Collections.EMPTY_MAP, + Collections.EMPTY_MAP, null); TaskLaunchRequest request2 = new TaskLaunchRequest(URI, - Collections.EMPTY_LIST, - Collections.EMPTY_MAP, - Collections.EMPTY_MAP); + Collections.EMPTY_LIST, Collections.EMPTY_MAP, + Collections.EMPTY_MAP, null); assertFalse(request.equals(null)); assertFalse(request.equals("nope")); assertTrue(request.equals(request)); assertTrue(request.equals(request2)); TaskLaunchRequest requestDiff = new TaskLaunchRequest("http://oops", - Collections.EMPTY_LIST, - Collections.EMPTY_MAP, - Collections.EMPTY_MAP); + Collections.EMPTY_LIST, Collections.EMPTY_MAP, + Collections.EMPTY_MAP, null); + assertFalse(request.equals(requestDiff)); + + requestDiff = new TaskLaunchRequest(URI, args, Collections.EMPTY_MAP, + Collections.EMPTY_MAP, null); assertFalse(request.equals(requestDiff)); requestDiff = new TaskLaunchRequest(URI, - args, - Collections.EMPTY_MAP, - Collections.EMPTY_MAP); - assertFalse(request.equals(requestDiff)); - - requestDiff = new TaskLaunchRequest(URI, - null, null, null); + null, null, null, null); assertTrue(request.equals(requestDiff)); - requestDiff = new TaskLaunchRequest(URI, - Collections.EMPTY_LIST, - map, - Collections.EMPTY_MAP); + requestDiff = new TaskLaunchRequest(URI, Collections.EMPTY_LIST, map, + Collections.EMPTY_MAP, null); assertFalse(request.equals(requestDiff)); - requestDiff = new TaskLaunchRequest(URI, - Collections.EMPTY_LIST, - Collections.EMPTY_MAP, - map); + requestDiff = new TaskLaunchRequest(URI, Collections.EMPTY_LIST, + Collections.EMPTY_MAP, map, null); assertFalse(request.equals(requestDiff)); assertEquals(request.hashCode(), request.hashCode()); } + + @Test + public void testApplicationName() { + TaskLaunchRequest request = new TaskLaunchRequest(URI, + Collections.EMPTY_LIST, Collections.EMPTY_MAP, + Collections.EMPTY_MAP, null); + assertTrue(request.getApplicationName().startsWith("Task-")); + + request = new TaskLaunchRequest(URI, + Collections.EMPTY_LIST, Collections.EMPTY_MAP, + Collections.EMPTY_MAP, APP_NAME); + assertEquals(APP_NAME, request.getApplicationName()); + } } diff --git a/spring-cloud-task-stream/src/test/java/org/springframework/cloud/task/launcher/TaskLauncherSinkTests.java b/spring-cloud-task-stream/src/test/java/org/springframework/cloud/task/launcher/TaskLauncherSinkTests.java index e95fd9a0..041f2fe9 100644 --- a/spring-cloud-task-stream/src/test/java/org/springframework/cloud/task/launcher/TaskLauncherSinkTests.java +++ b/spring-cloud-task-stream/src/test/java/org/springframework/cloud/task/launcher/TaskLauncherSinkTests.java @@ -26,23 +26,27 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.deployer.spi.task.LaunchState; -import org.springframework.cloud.stream.annotation.Bindings; import org.springframework.cloud.stream.messaging.Sink; import org.springframework.cloud.task.launcher.configuration.TaskConfiguration; import org.springframework.cloud.task.launcher.util.TaskLauncherSinkApplication; import org.springframework.context.ApplicationContext; import org.springframework.messaging.MessageHandlingException; import org.springframework.messaging.support.GenericMessage; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; -@RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = {TaskLauncherSinkApplication.class, TaskConfiguration.class} ) +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {TaskLauncherSinkApplication.class, TaskConfiguration.class} ) public class TaskLauncherSinkTests { + private final static String TASK_NAME_PREFIX = "Task-"; + + private final static String APP_NAME = "MY_APP_NAME"; + private final static String PARAM1 = "FOO"; private final static String PARAM2 = "BAR"; @@ -61,7 +65,6 @@ public class TaskLauncherSinkTests { private ApplicationContext context; @Autowired - @Bindings(TaskLauncherSink.class) private Sink sink; @Before @@ -72,29 +75,43 @@ public class TaskLauncherSinkTests { @Test public void testSuccessWithParams() { - List commandLineArgs = new ArrayList<>(); commandLineArgs.add(PARAM1); commandLineArgs.add(PARAM2); - TaskConfiguration.TestTaskLauncher testTaskLauncher = launchTask(VALID_URL, commandLineArgs); + TaskConfiguration.TestTaskLauncher testTaskLauncher = + launchTask(VALID_URL, commandLineArgs, null); assertEquals(LaunchState.complete, testTaskLauncher.status(DEFAULT_STATUS).getState()); assertEquals(2, testTaskLauncher.getCommandlineArguments().size()); - assertEquals(testTaskLauncher.getCommandlineArguments().get(0), PARAM1); - assertEquals(testTaskLauncher.getCommandlineArguments().get(1), PARAM2); + assertEquals(PARAM1, testTaskLauncher.getCommandlineArguments().get(0)); + assertEquals(PARAM2, testTaskLauncher.getCommandlineArguments().get(1)); + assertTrue(testTaskLauncher.getApplicationName().startsWith(TASK_NAME_PREFIX)); + } + + @Test + public void testSuccessWithAppName() { + TaskConfiguration.TestTaskLauncher testTaskLauncher = + launchTask(VALID_URL, null, APP_NAME); + + assertEquals(LaunchState.complete, testTaskLauncher.status(DEFAULT_STATUS).getState()); + assertEquals(0, testTaskLauncher.getCommandlineArguments().size()); + assertEquals(APP_NAME, testTaskLauncher.getApplicationName()); } @Test public void testSuccessNoParams() { - TaskConfiguration.TestTaskLauncher testTaskLauncher = launchTask(VALID_URL, null); + TaskConfiguration.TestTaskLauncher testTaskLauncher = + launchTask(VALID_URL, null, null); assertEquals(LaunchState.complete, testTaskLauncher.status(DEFAULT_STATUS).getState()); assertEquals(0, testTaskLauncher.getCommandlineArguments().size()); + assertTrue(testTaskLauncher.getApplicationName().startsWith(TASK_NAME_PREFIX)); } @Test(expected = MessageHandlingException.class) public void testInvalidJar() { - TaskConfiguration.TestTaskLauncher testTaskLauncher = launchTask(INVALID_URL, null); + TaskConfiguration.TestTaskLauncher testTaskLauncher = launchTask( + INVALID_URL, null, null); } @Test @@ -108,14 +125,17 @@ public class TaskLauncherSinkTests { @Test(expected = IllegalArgumentException.class) public void testNoTaskLauncher() { TaskLauncherSink sink = new TaskLauncherSink(); - sink.taskLauncherSink(new TaskLaunchRequest(VALID_URL, null, properties, null)); + sink.taskLauncherSink(new TaskLaunchRequest(VALID_URL, null, properties, + null, null)); } - private TaskConfiguration.TestTaskLauncher launchTask(String artifactURL, List commandLineArgs) { + private TaskConfiguration.TestTaskLauncher launchTask(String artifactURL, + List commandLineArgs, String applicationName) { TaskConfiguration.TestTaskLauncher testTaskLauncher = context.getBean(TaskConfiguration.TestTaskLauncher.class); - TaskLaunchRequest request = new TaskLaunchRequest(artifactURL, commandLineArgs, properties, null); + TaskLaunchRequest request = new TaskLaunchRequest(artifactURL, + commandLineArgs, properties, null, applicationName); GenericMessage message = new GenericMessage<>(request); this.sink.input().send(message); return testTaskLauncher; diff --git a/spring-cloud-task-stream/src/test/java/org/springframework/cloud/task/launcher/configuration/TaskConfiguration.java b/spring-cloud-task-stream/src/test/java/org/springframework/cloud/task/launcher/configuration/TaskConfiguration.java index df50d9a8..fd8f530b 100644 --- a/spring-cloud-task-stream/src/test/java/org/springframework/cloud/task/launcher/configuration/TaskConfiguration.java +++ b/spring-cloud-task-stream/src/test/java/org/springframework/cloud/task/launcher/configuration/TaskConfiguration.java @@ -45,10 +45,13 @@ public class TaskConfiguration { private List commandlineArguments; + private String applicationName; + @Override public String launch(AppDeploymentRequest request) { state = LaunchState.complete; this.commandlineArguments = request.getCommandlineArguments(); + this.applicationName = request.getDefinition().getName(); return null; } @@ -65,5 +68,9 @@ public class TaskConfiguration { public List getCommandlineArguments() { return commandlineArguments; } + + public String getApplicationName() { + return applicationName; + } } }