diff --git a/spring-cloud-task-integration-tests/pom.xml b/spring-cloud-task-integration-tests/pom.xml
index 26ce24b3..cfecb06f 100644
--- a/spring-cloud-task-integration-tests/pom.xml
+++ b/spring-cloud-task-integration-tests/pom.xml
@@ -46,6 +46,21 @@
org.springframework.cloud
spring-cloud-deployer-resource-support
+
+ org.springframework.cloud
+ spring-cloud-deployer-spi
+ test
+
+
+ org.springframework.cloud
+ spring-cloud-deployer-local
+ test
+
+
+ com.h2database
+ h2
+ test
+
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
new file mode 100644
index 00000000..1bd460dc
--- /dev/null
+++ b/spring-cloud-task-integration-tests/src/test/java/org/springframework/cloud/task/launcher/TaskLauncherSinkTests.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2016 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.launcher;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+import javax.sql.DataSource;
+
+import org.h2.tools.Server;
+import org.junit.Before;
+import org.junit.ClassRule;
+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.cloud.deployer.spi.local.LocalDeployerProperties;
+import org.springframework.cloud.deployer.spi.local.LocalTaskLauncher;
+import org.springframework.cloud.deployer.spi.task.TaskLauncher;
+import org.springframework.cloud.stream.annotation.Bindings;
+import org.springframework.cloud.stream.messaging.Sink;
+import org.springframework.cloud.stream.test.junit.rabbit.RabbitTestSupport;
+import org.springframework.cloud.task.launcher.util.TaskLauncherSinkApplication;
+import org.springframework.cloud.task.repository.TaskExecution;
+import org.springframework.cloud.task.repository.TaskExplorer;
+import org.springframework.cloud.task.repository.support.SimpleTaskExplorer;
+import org.springframework.cloud.task.repository.support.TaskExecutionDaoFactoryBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+import org.springframework.messaging.support.GenericMessage;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.util.SocketUtils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringApplicationConfiguration(classes = {TaskLauncherSinkApplication.class, TaskLauncherSinkTests.TaskLauncherConfiguration.class})
+public class TaskLauncherSinkTests {
+
+ private final static int WAIT_INTERVAL = 500;
+ private final static int MAX_WAIT_TIME = 5000;
+ private final static String URL = "maven://org.springframework.cloud.task.app:"
+ + "timestamp-task:jar:1.0.0.BUILD-SNAPSHOT";
+ private final static String DATASOURCE_URL;
+ private final static String DATASOURCE_USER_NAME = "SA";
+ private final static String DATASOURCE_USER_PASSWORD = "";
+ private final static String DATASOURCE_DRIVER_CLASS_NAME = "org.h2.Driver";
+
+ @ClassRule
+ public static RabbitTestSupport rabbitTestSupport = new RabbitTestSupport();
+
+
+ @Autowired
+ @Bindings(TaskLauncherSink.class)
+ private Sink sink;
+
+ @Autowired
+ public void setDataSource(DataSource dataSource) {
+ this.dataSource = dataSource;
+ taskExplorer = new SimpleTaskExplorer(new TaskExecutionDaoFactoryBean(dataSource));
+ }
+
+ private static int randomPort;
+
+ static {
+ randomPort = SocketUtils.findAvailableTcpPort();
+ DATASOURCE_URL = "jdbc:h2:tcp://localhost:" + randomPort + "/mem:dataflow;DB_CLOSE_DELAY=-1;"
+ + "DB_CLOSE_ON_EXIT=FALSE";
+ }
+
+ private DataSource dataSource;
+
+ private Map properties;
+
+ private TaskExplorer taskExplorer;
+
+ @Before
+ public void setup() {
+ properties = new HashMap<>();
+ properties.put("server.port", "0");
+ properties.put("spring.datasource.url", DATASOURCE_URL);
+ properties.put("spring.datasource.username", DATASOURCE_USER_NAME);
+ properties.put("spring.datasource.password", DATASOURCE_USER_PASSWORD);
+ properties.put("spring.datasource.driverClassName", DATASOURCE_DRIVER_CLASS_NAME);
+ }
+
+ @Test
+ public void testWithLocalDeployer() throws Exception {
+ launchTask(URL);
+ assertTrue(waitForDBToBePopulated());
+
+ Page taskExecutions = taskExplorer.findAll(new PageRequest(0, 10));
+ assertEquals("Only one row is expected", 1, taskExecutions.getTotalElements());
+ assertEquals("return code should be 0", 0, taskExecutions.iterator().next().getExitCode().intValue());
+ }
+
+ private boolean tableExists() throws SQLException {
+ boolean result = false;
+ try (
+ Connection conn = dataSource.getConnection();
+ ResultSet res = conn.getMetaData().getTables(null, null, "TASK_EXECUTION",
+ new String[]{"TABLE"});) {
+ result = res.next();
+ }
+ return result;
+ }
+
+ private boolean waitForDBToBePopulated() throws Exception {
+ boolean isDbPopulated = false;
+ for (int waitTime = 0; waitTime <= MAX_WAIT_TIME; waitTime += WAIT_INTERVAL) {
+ Thread.sleep(WAIT_INTERVAL);
+ if (tableExists() && taskExplorer.getTaskExecutionCount() > 0) {
+ isDbPopulated = true;
+ break;
+ }
+ }
+ return isDbPopulated;
+ }
+
+ private void launchTask(String artifactURL) {
+ TaskLaunchRequest request = new TaskLaunchRequest(artifactURL, null, this.properties, null);
+ GenericMessage message = new GenericMessage<>(request);
+ this.sink.input().send(message);
+ }
+
+ @Configuration
+ public static class TaskLauncherConfiguration {
+ @Bean
+ public TaskLauncher taskLauncher() {
+ LocalDeployerProperties props = new LocalDeployerProperties();
+ props.setDeleteFilesOnExit(false);
+
+ return new LocalTaskLauncher(props);
+ }
+
+ @Bean(destroyMethod = "stop")
+ public Server initH2TCPServer() {
+ Server server = null;
+ try {
+ server = Server.createTcpServer("-tcp", "-tcpAllowOthers", "-tcpPort",
+ String.valueOf(randomPort)).start();
+ }
+ catch (SQLException e) {
+ throw new IllegalStateException(e);
+ }
+ return server;
+ }
+
+ @Bean
+ public DataSource dataSource() {
+ DriverManagerDataSource dataSource = new DriverManagerDataSource();
+ dataSource.setDriverClassName(DATASOURCE_DRIVER_CLASS_NAME);
+ dataSource.setUrl(DATASOURCE_URL);
+ dataSource.setUsername(DATASOURCE_USER_NAME);
+ dataSource.setPassword(DATASOURCE_USER_PASSWORD);
+ return dataSource;
+ }
+ }
+
+}
diff --git a/spring-cloud-task-integration-tests/src/test/java/org/springframework/cloud/task/launcher/util/TaskLauncherSinkApplication.java b/spring-cloud-task-integration-tests/src/test/java/org/springframework/cloud/task/launcher/util/TaskLauncherSinkApplication.java
new file mode 100644
index 00000000..141d7eb3
--- /dev/null
+++ b/spring-cloud-task-integration-tests/src/test/java/org/springframework/cloud/task/launcher/util/TaskLauncherSinkApplication.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2016 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.launcher.util;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.task.launcher.annotation.EnableTaskLauncher;
+
+/**
+ * @author Glenn Renfro
+ */
+@SpringBootApplication
+@EnableTaskLauncher
+public class TaskLauncherSinkApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(TaskLauncherSinkApplication.class, args);
+ }
+}
diff --git a/spring-cloud-task-integration-tests/src/test/java/org/springframework/cloud/task/listener/BatchExecutionEventTests.java b/spring-cloud-task-integration-tests/src/test/java/org/springframework/cloud/task/listener/BatchExecutionEventTests.java
index 9780051b..6ae41d13 100644
--- a/spring-cloud-task-integration-tests/src/test/java/org/springframework/cloud/task/listener/BatchExecutionEventTests.java
+++ b/spring-cloud-task-integration-tests/src/test/java/org/springframework/cloud/task/listener/BatchExecutionEventTests.java
@@ -17,6 +17,7 @@
package org.springframework.cloud.task.listener;
+import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -27,15 +28,11 @@ import org.junit.ClassRule;
import org.junit.Test;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
-import org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
-import org.springframework.cloud.stream.binder.rabbit.config.RabbitServiceAutoConfiguration;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.cloud.stream.test.junit.rabbit.RabbitTestSupport;
-import org.springframework.cloud.task.batch.configuration.TaskBatchAutoConfiguration;
import org.springframework.cloud.task.batch.listener.BatchEventAutoConfiguration;
import org.springframework.cloud.task.batch.listener.support.JobExecutionEvent;
import org.springframework.cloud.task.batch.listener.support.StepExecutionEvent;
@@ -253,12 +250,6 @@ public class BatchExecutionEventTests {
private Object[] getConfigurations(Class sinkClazz, Class jobConfigurationClazz) {
return new Object[]{
jobConfigurationClazz,
- PropertyPlaceholderAutoConfiguration.class,
- BatchAutoConfiguration.class,
- TaskBatchAutoConfiguration.class,
- TaskEventAutoConfiguration.class,
- BatchEventAutoConfiguration.class,
- RabbitServiceAutoConfiguration.class,
sinkClazz };
}
@@ -268,6 +259,7 @@ public class BatchExecutionEventTests {
"--spring.main.web-environment=false",
"--spring.cloud.stream.defaultBinder=rabbit",
"--spring.cloud.stream.bindings.task-events.destination=test",
+ "foo=" + UUID.randomUUID().toString(),
sinkChannelParam };
}
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 2ea7f6eb..fb7be7df 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
@@ -35,6 +35,7 @@ import org.springframework.cloud.stream.test.junit.rabbit.RabbitTestSupport;
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;
@@ -48,6 +49,12 @@ public class TaskLauncherSinkTests {
private final static String PARAM2 = "BAR";
+ private final static String VALID_URL = "maven://org.springframework.cloud.task.app:"
+ + "timestamp-task:jar:1.0.0.BUILD-SNAPSHOT";
+
+ private final static String INVALID_URL = "maven://not.real.group:"
+ + "invalid:jar:1.0.0.BUILD-SNAPSHOT";
+
private Map properties;
@ClassRule
@@ -75,7 +82,7 @@ public class TaskLauncherSinkTests {
commandLineArgs.add(PARAM1);
commandLineArgs.add(PARAM2);
- TaskConfiguration.TestTaskLauncher testTaskLauncher = launchTask(commandLineArgs);
+ TaskConfiguration.TestTaskLauncher testTaskLauncher = launchTask(VALID_URL, commandLineArgs);
assertEquals(LaunchState.complete, testTaskLauncher.status(DEFAULT_STATUS).getState());
assertEquals(2, testTaskLauncher.getCommandlineArguments().size());
@@ -85,11 +92,16 @@ public class TaskLauncherSinkTests {
@Test
public void testSuccessNoParams() {
- TaskConfiguration.TestTaskLauncher testTaskLauncher= launchTask(null);
+ TaskConfiguration.TestTaskLauncher testTaskLauncher = launchTask(VALID_URL, null);
assertEquals(LaunchState.complete, testTaskLauncher.status(DEFAULT_STATUS).getState());
assertEquals(0, testTaskLauncher.getCommandlineArguments().size());
}
+ @Test(expected = MessageHandlingException.class)
+ public void testInvalidJar() {
+ TaskConfiguration.TestTaskLauncher testTaskLauncher = launchTask(INVALID_URL, null);
+ }
+
@Test
public void testNoRun() {
TaskConfiguration.TestTaskLauncher testTaskLauncher =
@@ -101,16 +113,14 @@ public class TaskLauncherSinkTests {
@Test(expected = IllegalArgumentException.class)
public void testNoTaskLauncher() {
TaskLauncherSink sink = new TaskLauncherSink();
- sink.taskLauncherSink(new TaskLaunchRequest("maven://org.springframework.cloud.task.app:"
- + "timestamp-task:jar:1.0.0.BUILD-SNAPSHOT",null, properties, null));
+ sink.taskLauncherSink(new TaskLaunchRequest(VALID_URL, null, properties, null));
}
- private TaskConfiguration.TestTaskLauncher launchTask(List commandLineArgs) {
+ private TaskConfiguration.TestTaskLauncher launchTask(String artifactURL, List commandLineArgs) {
TaskConfiguration.TestTaskLauncher testTaskLauncher =
context.getBean(TaskConfiguration.TestTaskLauncher.class);
- TaskLaunchRequest request = new TaskLaunchRequest("maven://org.springframework.cloud.task.app:"
- + "timestamp-task:jar:1.0.0.BUILD-SNAPSHOT",commandLineArgs, properties, null);
+ TaskLaunchRequest request = new TaskLaunchRequest(artifactURL, commandLineArgs, properties, null);
GenericMessage message = new GenericMessage<>(request);
this.sink.input().send(message);
return testTaskLauncher;