diff --git a/spring-cloud-task-core/pom.xml b/spring-cloud-task-core/pom.xml
index dd1a6acb..efce4710 100755
--- a/spring-cloud-task-core/pom.xml
+++ b/spring-cloud-task-core/pom.xml
@@ -27,6 +27,10 @@
org.springframework.boot
spring-boot
+
+ org.springframework.boot
+ spring-boot-autoconfigure
+
org.springframework
spring-context
@@ -40,13 +44,12 @@
spring-aop
- org.aspectj
- aspectjweaver
+ org.springframework
+ spring-jdbc
- junit
- junit
- test
+ org.aspectj
+ aspectjweaver
org.springframework
@@ -58,6 +61,16 @@
mockito-core
test
+
+ org.hsqldb
+ hsqldb
+ test
+
+
+ org.apache.tomcat
+ tomcat-jdbc
+ test
+
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/annotation/EnableTask.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/annotation/EnableTask.java
index ad871440..d1e266a1 100644
--- a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/annotation/EnableTask.java
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/annotation/EnableTask.java
@@ -54,7 +54,7 @@ import org.springframework.context.annotation.Import;
* You will also be able to @Autowired some useful stuff into your context:
*
*
- * - a {@link TaskRepository} (bean name "taskRepository").
+ * - a {@link TaskRepository} (bean name "taskRepository").
*
*
* @author Glenn Renfro
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/annotation/package-info.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/annotation/package-info.java
new file mode 100644
index 00000000..22b902ff
--- /dev/null
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/annotation/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Annotations for spring cloud task.
+ */
+package org.springframework.cloud.task.annotation;
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/DefaultTaskConfigurer.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/DefaultTaskConfigurer.java
index 874eb1f5..d40b1c18 100644
--- a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/DefaultTaskConfigurer.java
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/DefaultTaskConfigurer.java
@@ -16,27 +16,68 @@
package org.springframework.cloud.task.configuration;
+import javax.sql.DataSource;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cloud.task.repository.TaskExplorer;
import org.springframework.cloud.task.repository.TaskRepository;
-import org.springframework.cloud.task.repository.support.LoggerTaskRepository;
+import org.springframework.cloud.task.repository.dao.JdbcTaskExecutionDao;
+import org.springframework.cloud.task.repository.dao.MapTaskExecutionDao;
+import org.springframework.cloud.task.repository.support.JdbcTaskRepositoryFactoryBean;
+import org.springframework.cloud.task.repository.support.MapTaskRepositoryFactoryBean;
+import org.springframework.cloud.task.repository.support.SimpleTaskRepository;
/**
- * If no {@link TaskConfigurer} is present, then this configuration will be used.
+ * Default implementation of the TaskConfigurer interface. If no {@link TaskConfigurer}
+ * implementation is present, then this configuration will be used.
* The following defaults will be used:
- *
*
- * - {@link LoggerTaskRepository} will be the default {@link TaskRepository}.
+ * - {@link SimpleTaskRepository} is the default {@link TaskRepository} returned.
+ * If a data source is present then a data will be stored in the database {@link JdbcTaskExecutionDao} else it will
+ * be stored in a map {@link MapTaskExecutionDao}.
*
*
- *
* @author Glenn Renfro
*/
-public class DefaultTaskConfigurer implements TaskConfigurer{
+public class DefaultTaskConfigurer implements TaskConfigurer {
+
+ private final static Logger logger = LoggerFactory.getLogger(DefaultTaskConfigurer.class);
+
+ private DataSource dataSource;
+
+ private TaskRepository taskRepository;
public DefaultTaskConfigurer(){
+ initialize();
+ }
+
+ public DefaultTaskConfigurer(DataSource dataSource) {
+ this.dataSource = dataSource;
+ initialize();
}
public TaskRepository getTaskRepository() {
- return new LoggerTaskRepository();
+ return taskRepository;
+ }
+
+ public TaskExplorer getTaskExplorer() {
+ throw new UnsupportedOperationException("method not implemented");
+ //TODO if datasource != null use TaskRepositoryFactoryBean from above like initialize method in DefaultBatchConfigurer
+ }
+
+ private void initialize(){
+ logger.debug("Initializing TaskRepository");
+ if (dataSource == null) {
+ MapTaskRepositoryFactoryBean mapTaskRepositoryFactoryBean =
+ new MapTaskRepositoryFactoryBean();
+ taskRepository = mapTaskRepositoryFactoryBean.getObject();
+ }
+ else {
+ JdbcTaskRepositoryFactoryBean jdbcTaskRepositoryFactoryBean =
+ new JdbcTaskRepositoryFactoryBean(dataSource);
+ taskRepository = jdbcTaskRepositoryFactoryBean.getObject();
+ }
}
}
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/SimpleTaskConfiguration.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/SimpleTaskConfiguration.java
index f61d22d9..10c599d2 100644
--- a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/SimpleTaskConfiguration.java
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/SimpleTaskConfiguration.java
@@ -19,13 +19,20 @@ package org.springframework.cloud.task.configuration;
import java.util.Collection;
import javax.annotation.PostConstruct;
+import javax.sql.DataSource;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.task.repository.TaskRepository;
+import org.springframework.cloud.task.repository.support.TaskDatabaseInitializer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* Base {@code Configuration} class providing common structure for enabling and using
@@ -34,12 +41,25 @@ import org.springframework.context.annotation.Scope;
*
* @author Glenn Renfro
*/
+@EnableTransactionManagement
@Configuration
public class SimpleTaskConfiguration {
+ protected static final Log logger = LogFactory.getLog(SimpleTaskConfiguration.class);
+
+
@Autowired
private ApplicationContext context;
+ @Autowired(required = false)
+ private Collection dataSources;
+
+ @Autowired
+ private ResourceLoader resourceLoader;
+
+ @Value("${spring.class.initialize.enable:true}")
+ private boolean taskInitializationEnable;
+
private boolean initialized = false;
private TaskRepository taskRepository;
@@ -56,7 +76,7 @@ public class SimpleTaskConfiguration {
public TaskRepository taskRepository(){
return taskRepository;
}
-
+
/**
* Sets up the basic components by extracting them from the {@link TaskConfigurer}, defaulting to some
* sensible values as long as a unique DataSource is available.
@@ -66,6 +86,7 @@ public class SimpleTaskConfiguration {
if (initialized) {
return;
}
+ logger.debug("Getting Task Configurer");
TaskConfigurer configurer = getConfigurer(context.getBeansOfType(TaskConfigurer.class).values());
taskRepository = configurer.getTaskRepository();
initialized = true;
@@ -73,12 +94,32 @@ public class SimpleTaskConfiguration {
private TaskConfigurer getConfigurer(Collection configurers) {
if (this.configurer != null) {
+ logger.debug(String.format("Using %s TaskConfigurer",
+ configurer.getClass().getName()));
return this.configurer;
}
if (configurers == null || configurers.isEmpty()) {
- DefaultTaskConfigurer configurer = new DefaultTaskConfigurer();
- this.configurer = configurer;
- return configurer;
+ if (dataSources == null || dataSources.isEmpty()) {
+ this.configurer = new DefaultTaskConfigurer();
+ logger.debug(String.format("Using %s TaskConfigurer, with no datasource",
+ configurer.getClass().getName()));
+ return this.configurer;
+ }
+ else if (dataSources != null && dataSources.size() == 1) {
+ DataSource dataSource = dataSources.iterator().next();
+ if(taskInitializationEnable) {
+ logger.debug("Initializing Task Schema");
+ TaskDatabaseInitializer.initializeDatabase(dataSource, resourceLoader);
+ }
+ this.configurer = new DefaultTaskConfigurer(dataSource);
+ logger.debug(String.format("Using %s TaskConfigurer, with datasource",
+ configurer.getClass().getName()));
+ return this.configurer;
+ }
+ else {
+ throw new IllegalStateException("To use the default TaskConfigurer the context must contain no more than" +
+ "one DataSource, found " + dataSources.size());
+ }
}
if (configurers.size() > 1) {
throw new IllegalStateException(
@@ -86,6 +127,9 @@ public class SimpleTaskConfiguration {
+ configurers.size());
}
this.configurer = configurers.iterator().next();
+ logger.debug(String.format("More than one Task Configurer available. Using"
+ + " first in list: %s TaskConfigurer",
+ configurer.getClass().getName()));
return this.configurer;
}
}
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/package-info.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/package-info.java
new file mode 100644
index 00000000..8bbdd330
--- /dev/null
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/configuration/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Interfaces for configuring Spring Cloud Task and a default implementations.
+ */
+package org.springframework.cloud.task.configuration;
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/package-info.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/package-info.java
new file mode 100644
index 00000000..235956ad
--- /dev/null
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Base package for spring cloud task.
+ */
+package org.springframework.cloud.task;
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/TaskExecution.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/TaskExecution.java
index a07adde5..4ccc6906 100644
--- a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/TaskExecution.java
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/TaskExecution.java
@@ -16,9 +16,12 @@
package org.springframework.cloud.task.repository;
+import java.util.ArrayList;
import java.util.Date;
import java.util.List;
+import org.springframework.util.Assert;
+
/**
* Represents the state of the Task for each execution.
*
@@ -26,23 +29,6 @@ import java.util.List;
*/
public class TaskExecution {
-
- public TaskExecution() {
- }
-
- public TaskExecution(String executionId, int exitCode, String taskName,
- Date startTime, Date endTime, String statusCode,
- String exitMessage, List parameters) {
- this.executionId = executionId;
- this.exitCode = exitCode;
- this.taskName = taskName;
- this.startTime = startTime;
- this.endTime = endTime;
- this.statusCode = statusCode;
- this.exitMessage = exitMessage;
- this.parameters = parameters;
- }
-
/**
* The unique id associated with the task execution.
*/
@@ -83,6 +69,27 @@ public class TaskExecution {
*/
private List parameters;
+ public TaskExecution() {
+ parameters = new ArrayList<>();
+ }
+
+ public TaskExecution(String executionId, int exitCode, String taskName,
+ Date startTime, Date endTime, String statusCode,
+ String exitMessage, List parameters) {
+
+ Assert.hasText(executionId, "executionId must not be null nor empty");
+ Assert.notNull(parameters, "parameters must not be null");
+ Assert.notNull(startTime, "startTime must not be null");
+ this.executionId = executionId;
+ this.exitCode = exitCode;
+ this.taskName = taskName;
+ this.startTime = startTime;
+ this.endTime = endTime;
+ this.statusCode = statusCode;
+ this.exitMessage = exitMessage;
+ this.parameters = parameters;
+ }
+
public String getExecutionId() {
return executionId;
}
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/TaskRepository.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/TaskRepository.java
index 75737010..f727ac29 100644
--- a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/TaskRepository.java
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/TaskRepository.java
@@ -16,6 +16,8 @@
package org.springframework.cloud.task.repository;
+import org.springframework.transaction.annotation.Transactional;
+
/**
* TaskRepository interface offers methods that create and update task execution
* information.
@@ -36,5 +38,6 @@ public interface TaskRepository {
*
* @param taskExecution taskExecution to be recorded
*/
+ @Transactional
public void createTaskExecution(TaskExecution taskExecution);
}
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/dao/JdbcTaskExecutionDao.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/dao/JdbcTaskExecutionDao.java
new file mode 100644
index 00000000..b55be4bf
--- /dev/null
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/dao/JdbcTaskExecutionDao.java
@@ -0,0 +1,142 @@
+/*
+ * 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.repository.dao;
+
+import java.sql.Types;
+import java.util.Date;
+import java.util.List;
+
+import javax.sql.DataSource;
+
+import org.springframework.cloud.task.repository.TaskExecution;
+import org.springframework.jdbc.core.JdbcOperations;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.util.Assert;
+import org.springframework.util.StringUtils;
+
+/**
+ * Stores Task Execution Information to a JDBC DataSource.
+ *
+ * @author Glenn Renfro
+ */
+public class JdbcTaskExecutionDao implements TaskExecutionDao {
+
+
+ private static final String SAVE_TASK_EXECUTION = "INSERT into %PREFIX%EXECUTION"
+ + "(TASK_EXECUTION_ID, START_TIME, END_TIME, TASK_NAME, EXIT_CODE, "
+ + "EXIT_MESSAGE, LAST_UPDATED, STATUS_CODE) values (?, ?, ?, ?, ?, ?, ?, ?)";
+
+ private static final String CREATE_TASK_PARAMETER = "INSERT into "
+ + "%PREFIX%EXECUTION_PARAMS(TASK_EXECUTION_ID, TASK_PARAM ) values (?, ?)";
+
+ private static final String CHECK_TASK_EXECUTION_EXISTS = "SELECT COUNT(*) FROM "
+ + "%PREFIX%EXECUTION WHERE TASK_EXECUTION_ID = ?";
+
+ private static final String UPDATE_TASK_EXECUTION = "UPDATE %PREFIX%EXECUTION set "
+ + "START_TIME = ?, END_TIME = ?, TASK_NAME = ?, EXIT_CODE = ?, "
+ + "EXIT_MESSAGE = ?, LAST_UPDATED = ?, STATUS_CODE = ? "
+ + "where TASK_EXECUTION_ID = ?";
+
+
+ private static final String DEFAULT_TABLE_PREFIX = "TASK_";
+
+ private String tablePrefix = DEFAULT_TABLE_PREFIX;
+
+ private JdbcOperations jdbcTemplate;
+
+ public JdbcTaskExecutionDao(DataSource dataSource) {
+ Assert.notNull(dataSource);
+ this.jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+
+ @Override
+ public void saveTaskExecution(TaskExecution taskExecution) {
+ Object[] parameters = new Object[]{ taskExecution.getExecutionId(),
+ taskExecution.getStartTime(), taskExecution.getEndTime(),
+ taskExecution.getTaskName(), taskExecution.getExitCode(),
+ taskExecution.getExitMessage(), new Date(),
+ taskExecution.getStatusCode() };
+ int addCount = jdbcTemplate.update(
+ getQuery(SAVE_TASK_EXECUTION),
+ parameters,
+ new int[]{ Types.VARCHAR, Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR,
+ Types.INTEGER, Types.VARCHAR, Types.TIMESTAMP, Types.VARCHAR });
+ insertJobParameters(taskExecution.getExecutionId(), taskExecution.getParameters());
+ }
+
+ @Override
+ public void updateTaskExecution(TaskExecution taskExecution) {
+ // Check if given TaskExecution's Id already exists, if none is found
+ // it is invalid and an exception should be thrown.
+ if (jdbcTemplate.queryForObject(getQuery(CHECK_TASK_EXECUTION_EXISTS), Integer.class,
+ new Object[]{ taskExecution.getExecutionId() }) != 1) {
+ throw new IllegalStateException("Invalid TaskExecution, ID " + taskExecution.getExecutionId() + " not found.");
+ }
+
+ Object[] parameters = new Object[]{ taskExecution.getStartTime(), taskExecution.getEndTime(),
+ taskExecution.getTaskName(), taskExecution.getExitCode(),
+ taskExecution.getExitMessage(), new Date(), taskExecution.getStatusCode(),
+ taskExecution.getExecutionId() };
+ int count = jdbcTemplate.update(
+ getQuery(UPDATE_TASK_EXECUTION),
+ parameters,
+ new int[]{ Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.INTEGER,
+ Types.VARCHAR, Types.TIMESTAMP, Types.VARCHAR, Types.VARCHAR });
+ }
+
+ /**
+ * Public setter for the table prefix property. This will be prefixed to all
+ * the table names before queries are executed. Defaults to
+ * {@link #DEFAULT_TABLE_PREFIX}.
+ *
+ * @param tablePrefix the tablePrefix to set
+ */
+ public void setTablePrefix(String tablePrefix) {
+ this.tablePrefix = tablePrefix;
+ }
+
+ private String getQuery(String base) {
+ return StringUtils.replace(base, "%PREFIX%", tablePrefix);
+ }
+
+ /**
+ * Convenience method that inserts all parameters from the provided
+ * task parameters.
+ *
+ * @param executionId The executionId to which the params are associated.
+ * @param taskParameters The parameters to be stored.
+ */
+ private void insertJobParameters(String executionId, List taskParameters) {
+ for (String param : taskParameters) {
+ insertParameter(executionId, param);
+ }
+ }
+
+ /**
+ * Convenience method that inserts an individual records into the
+ * TASK_EXECUTION_PARAMS table.
+ */
+ private void insertParameter(String executionId, String param) {
+
+ Object[] args = new Object[0];
+ int[] argTypes = new int[]{ Types.VARCHAR, Types.VARCHAR };
+
+ args = new Object[]{ executionId, param };
+ jdbcTemplate.update(getQuery(CREATE_TASK_PARAMETER), args, argTypes);
+ }
+
+}
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/dao/MapTaskExecutionDao.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/dao/MapTaskExecutionDao.java
new file mode 100644
index 00000000..5bb7d547
--- /dev/null
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/dao/MapTaskExecutionDao.java
@@ -0,0 +1,52 @@
+/*
+ * 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.repository.dao;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.springframework.cloud.task.repository.TaskExecution;
+
+/**
+ * Stores Task Execution Information to a in-memory map.
+ *
+ * @author Glenn Renfro
+ */
+public class MapTaskExecutionDao implements TaskExecutionDao {
+
+ private ConcurrentMap taskExecutions;
+
+ public MapTaskExecutionDao() {
+ taskExecutions = new ConcurrentHashMap<>();
+ }
+
+ @Override
+ public void saveTaskExecution(TaskExecution taskExecution) {
+ taskExecutions.put(taskExecution.getExecutionId(), taskExecution);
+ }
+
+ @Override
+ public void updateTaskExecution(TaskExecution taskExecution) {
+ taskExecutions.put(taskExecution.getExecutionId(), taskExecution);
+ }
+
+ public Map getTaskExecutions(){
+ return Collections.unmodifiableMap(taskExecutions);
+ }
+}
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/LoggerTaskRepository.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/dao/TaskExecutionDao.java
similarity index 51%
rename from spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/LoggerTaskRepository.java
rename to spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/dao/TaskExecutionDao.java
index ef6ba1bc..b22c38f0 100644
--- a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/LoggerTaskRepository.java
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/dao/TaskExecutionDao.java
@@ -14,30 +14,28 @@
* limitations under the License.
*/
-package org.springframework.cloud.task.repository.support;
-
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+package org.springframework.cloud.task.repository.dao;
import org.springframework.cloud.task.repository.TaskExecution;
-import org.springframework.cloud.task.repository.TaskRepository;
/**
- * {@link TaskRepository} implementation that will log the task execution information.
+ * Data Access Object for task executions.
*
* @author Glenn Renfro
*/
-public class LoggerTaskRepository implements TaskRepository {
- private final static Logger logger = LoggerFactory.getLogger(LoggerTaskRepository.class);
+public interface TaskExecutionDao {
- @Override
- public void update(TaskExecution taskExecution) {
- logger.info("Updating: " + taskExecution.toString());
- }
+ /**
+ * Save a new {@link TaskExecution}.
+ *
+ * @param taskExecution the taskExecution to be stored.
+ */
+ void saveTaskExecution(TaskExecution taskExecution);
- @Override
- public void createTaskExecution(TaskExecution taskExecution) {
- logger.info("Creating: " + taskExecution.toString());
- }
+ /**
+ * Update and existing {@link TaskExecution}.
+ *
+ * @param taskExecution the taskExecution to be updated.
+ */
+ void updateTaskExecution(TaskExecution taskExecution);
}
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/dao/package-info.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/dao/package-info.java
new file mode 100644
index 00000000..e7bbc5ba
--- /dev/null
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/dao/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * Interface DAO and default implementations for storing and retrieving data for tasks
+ * from a repository.
+ */
+package org.springframework.cloud.task.repository.dao;
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/DatabaseType.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/DatabaseType.java
new file mode 100644
index 00000000..d98d68f3
--- /dev/null
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/DatabaseType.java
@@ -0,0 +1,104 @@
+/*
+ * 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.repository.support;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.sql.DataSource;
+
+import org.springframework.jdbc.support.JdbcUtils;
+import org.springframework.jdbc.support.MetaDataAccessException;
+import org.springframework.util.StringUtils;
+
+
+/**
+ * Enum representing a database type, such as DB2 or oracle. The type also
+ * contains a product name, which is expected to be the same as the product name
+ * provided by the database driver's metadata.
+ *
+ * @author Glenn Renfro
+ */
+public enum DatabaseType {
+
+ HSQL("HSQL Database Engine"),
+ ORACLE("Oracle"),
+ POSTGRES("PostgreSQL");
+
+ private static final Map dbNameMap;
+
+ private final String productName;
+
+ private DatabaseType(String productName) {
+ this.productName = productName;
+ }
+
+ static{
+ dbNameMap = new HashMap();
+ for(DatabaseType type: values()){
+ dbNameMap.put(type.getProductName(), type);
+ }
+ }
+
+ /**
+ * Convenience method that pulls a database product name from the DataSource's metadata.
+ *
+ * @param dataSource the datasource used to extact metadata.
+ * @return DatabaseType The database type associated with the datasource.
+ * @throws MetaDataAccessException thrown if failure occurs on metadata lookup.
+ */
+ public static DatabaseType fromMetaData(DataSource dataSource) throws MetaDataAccessException {
+ String databaseProductName =
+ JdbcUtils.extractDatabaseMetaData(dataSource, "getDatabaseProductName").toString();
+ if (StringUtils.hasText(databaseProductName) && !databaseProductName.equals("DB2/Linux") && databaseProductName.startsWith("DB2")) {
+ String databaseProductVersion =
+ JdbcUtils.extractDatabaseMetaData(dataSource, "getDatabaseProductVersion").toString();
+ if (!databaseProductVersion.startsWith("SQL")) {
+ databaseProductName = "DB2ZOS";
+ }
+ else {
+ databaseProductName = JdbcUtils.commonDatabaseName(databaseProductName);
+ }
+ }
+ else {
+ databaseProductName = JdbcUtils.commonDatabaseName(databaseProductName);
+ }
+ return fromProductName(databaseProductName);
+ }
+
+ /**
+ * Static method to obtain a DatabaseType from the provided product name.
+ *
+ * @param productName the name of the database.
+ * @return DatabaseType for given product name.
+ * @throws IllegalArgumentException if none is found.
+ */
+ public static DatabaseType fromProductName(String productName){
+ if(!dbNameMap.containsKey(productName)){
+ throw new IllegalArgumentException("DatabaseType not found for product name: [" +
+ productName + "]");
+ }
+ else{
+ return dbNameMap.get(productName);
+ }
+ }
+
+ private String getProductName() {
+ return productName;
+ }
+
+}
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/JdbcTaskRepositoryFactoryBean.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/JdbcTaskRepositoryFactoryBean.java
new file mode 100644
index 00000000..284fe20d
--- /dev/null
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/JdbcTaskRepositoryFactoryBean.java
@@ -0,0 +1,79 @@
+/*
+ * 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.repository.support;
+
+import javax.sql.DataSource;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.cloud.task.repository.TaskRepository;
+import org.springframework.cloud.task.repository.dao.JdbcTaskExecutionDao;
+import org.springframework.cloud.task.repository.dao.TaskExecutionDao;
+
+/**
+ * Automates the creation of a {@link SimpleTaskRepository} which will persist task
+ * execution data into a database. Requires the user to describe what kind of database
+ * they are using.
+ *
+ * @author Glenn Renfro
+ */
+public class JdbcTaskRepositoryFactoryBean {
+
+ public static final String DEFAULT_TABLE_PREFIX = "TASK_";
+
+ private static final Log logger = LogFactory.getLog(JdbcTaskRepositoryFactoryBean.class);
+
+ private DataSource dataSource;
+
+ private String tablePrefix = DEFAULT_TABLE_PREFIX;
+
+ public JdbcTaskRepositoryFactoryBean(){
+
+ }
+
+ public JdbcTaskRepositoryFactoryBean(DataSource dataSource) {
+ if(dataSource != null) {
+ this.dataSource = dataSource;
+ }
+ }
+
+ /**
+ * Sets the table prefix for all the batch meta-data tables.
+ * @param tablePrefix prefix prepended to batch meta-data tables
+ */
+ public void setTablePrefix(String tablePrefix) {
+ this.tablePrefix = tablePrefix;
+ }
+
+ /**
+ * Returns the a simpleTaskRepository that utilizes a MapTaskExecutionDao
+ * @return instance of task repository.
+ */
+ public TaskRepository getObject(){
+ TaskRepository taskRepository = null;
+ logger.debug(String.format("Creating SimpleTaskRepository that will use a %s",
+ JdbcTaskExecutionDao.class.getName()));
+ taskRepository = new SimpleTaskRepository(createJdbcTaskExecutionDao());
+ return taskRepository;
+ }
+
+ private TaskExecutionDao createJdbcTaskExecutionDao() {
+ JdbcTaskExecutionDao dao = new JdbcTaskExecutionDao(dataSource);
+ dao.setTablePrefix(tablePrefix);
+ return dao;
+ }
+}
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/MapTaskRepositoryFactoryBean.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/MapTaskRepositoryFactoryBean.java
new file mode 100644
index 00000000..e3698a8d
--- /dev/null
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/MapTaskRepositoryFactoryBean.java
@@ -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.task.repository.support;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.cloud.task.repository.TaskRepository;
+import org.springframework.cloud.task.repository.dao.MapTaskExecutionDao;
+
+/**
+ * Automates the creation of a {@link SimpleTaskRepository} which will persist task
+ * execution data into an in memory map. This is meant for development
+ * purposes and not for production use.
+ *
+ * @author Glenn Renfro
+ */
+public class MapTaskRepositoryFactoryBean {
+
+ private static final Log logger = LogFactory.getLog(MapTaskRepositoryFactoryBean.class);
+
+ private TaskRepository taskRepository;
+
+ public MapTaskRepositoryFactoryBean(){
+ logger.debug(String.format("Creating SimpleTaskRepository that will use a %s",
+ MapTaskExecutionDao.class.getName()));
+ taskRepository = new SimpleTaskRepository(new MapTaskExecutionDao());
+ }
+
+ /**
+ * Returns the a simpleTaskRepository that utilizes a MapTaskExecutionDao
+ * @return instance of task repository.
+ */
+ public TaskRepository getObject(){
+ return taskRepository;
+ }
+}
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/SimpleTaskRepository.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/SimpleTaskRepository.java
new file mode 100644
index 00000000..3d626726
--- /dev/null
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/SimpleTaskRepository.java
@@ -0,0 +1,73 @@
+/*
+ * 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.repository.support;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cloud.task.repository.TaskExecution;
+import org.springframework.cloud.task.repository.TaskRepository;
+import org.springframework.cloud.task.repository.dao.TaskExecutionDao;
+import org.springframework.util.Assert;
+
+/**
+ * Records the task execution information to the log and to TaskExecutionDao provided.
+ * @author Glenn Renfro
+ */
+public class SimpleTaskRepository implements TaskRepository {
+
+ private final static Logger logger = LoggerFactory.getLogger(SimpleTaskRepository.class);
+
+ private TaskExecutionDao taskExecutionDao;
+
+ public SimpleTaskRepository(TaskExecutionDao taskExecutionDao){
+ this.taskExecutionDao = taskExecutionDao;
+ }
+
+ @Override
+ public void update(TaskExecution taskExecution) {
+ validateTaskExecution(taskExecution);
+ taskExecutionDao.updateTaskExecution(taskExecution);
+ logger.info("Updating: " + taskExecution.toString());
+ }
+
+ @Override
+ public void createTaskExecution(TaskExecution taskExecution) {
+ validateTaskExecution(taskExecution);
+ taskExecutionDao.saveTaskExecution(taskExecution);
+ logger.info("Creating: " + taskExecution.toString());
+ }
+
+
+ /**
+ * Retrieves the taskExecutionDao associated with this repository.
+ * @return the taskExecutionDao
+ */
+ public TaskExecutionDao getTaskExecutionDao() {
+ return taskExecutionDao;
+ }
+
+ /**
+ * Validate TaskExecution. At a minimum a startTime.
+ *
+ * @param taskExecution the taskExecution to be evaluagted.
+ */
+ private void validateTaskExecution(TaskExecution taskExecution) {
+ Assert.notNull(taskExecution, "taskExecution should not be null");
+ Assert.notNull(taskExecution.getExecutionId(), "taskExecutionId should not be null");
+ Assert.notNull(taskExecution.getStartTime(), "TaskExecution start time cannot be null.");
+ }
+}
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/TaskDatabaseInitializer.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/TaskDatabaseInitializer.java
new file mode 100644
index 00000000..b98a97e8
--- /dev/null
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/TaskDatabaseInitializer.java
@@ -0,0 +1,76 @@
+/*
+ * 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.repository.support;
+
+import javax.sql.DataSource;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
+import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
+import org.springframework.jdbc.support.MetaDataAccessException;
+
+/**
+ * @author Glenn Renfro
+ */
+
+public class TaskDatabaseInitializer {
+
+ private static final Log logger = LogFactory.getLog(TaskDatabaseInitializer.class);
+
+ private static final String DEFAULT_SCHEMA_LOCATION = "classpath:org/springframework/"
+ + "cloud/task/schema-@@platform@@.sql";
+
+ /**
+ * Path to the SQL file to use to initialize the database schema.
+ */
+ private static String schema = DEFAULT_SCHEMA_LOCATION;
+
+ public static void initializeDatabase(DataSource dataSource, ResourceLoader resourceLoader) {
+ if (dataSource != null) {
+ String platform = getDatabaseType(dataSource);
+ if ("hsql".equals(platform)) {
+ platform = "hsqldb";
+ }
+ if ("postgres".equals(platform)) {
+ platform = "postgresql";
+ }
+ if ("oracle".equals(platform)) {
+ platform = "oracle10g";
+ }
+ ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
+ String schemaLocation = schema;
+ schemaLocation = schemaLocation.replace("@@platform@@", platform);
+ populator.addScript(resourceLoader.getResource(schemaLocation));
+ populator.setContinueOnError(false);
+ logger.debug(String.format("Initializing task schema for %s database",
+ platform));
+ DatabasePopulatorUtils.execute(populator, dataSource);
+ }
+ }
+
+ private static String getDatabaseType(DataSource dataSource) {
+ try {
+ return DatabaseType.fromMetaData(dataSource).toString().toLowerCase();
+ }
+ catch (MetaDataAccessException ex) {
+ throw new IllegalStateException("Unable to detect database type", ex);
+ }
+ }
+
+}
diff --git a/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/package-info.java b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/package-info.java
new file mode 100644
index 00000000..95223cf3
--- /dev/null
+++ b/spring-cloud-task-core/src/main/java/org/springframework/cloud/task/repository/support/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Classes used for setting up and supporting a task repositories.
+ */
+package org.springframework.cloud.task.repository.support;
diff --git a/spring-cloud-task-core/src/main/resources/org/springframework/cloud/task/schema-hsqldb.sql b/spring-cloud-task-core/src/main/resources/org/springframework/cloud/task/schema-hsqldb.sql
new file mode 100644
index 00000000..0901c276
--- /dev/null
+++ b/spring-cloud-task-core/src/main/resources/org/springframework/cloud/task/schema-hsqldb.sql
@@ -0,0 +1,18 @@
+
+CREATE TABLE TASK_EXECUTION (
+ TASK_EXECUTION_ID VARCHAR(100) NOT NULL PRIMARY KEY ,
+ START_TIME TIMESTAMP DEFAULT NULL ,
+ END_TIME TIMESTAMP DEFAULT NULL ,
+ TASK_NAME VARCHAR(100) ,
+ EXIT_CODE INTEGER ,
+ EXIT_MESSAGE VARCHAR(2500) ,
+ LAST_UPDATED TIMESTAMP ,
+ STATUS_CODE VARCHAR(10)
+);
+
+CREATE TABLE TASK_EXECUTION_PARAMS (
+ TASK_EXECUTION_ID VARCHAR(100) NOT NULL ,
+ TASK_PARAM VARCHAR(250) ,
+ constraint TASK_EXEC_PARAMS_FK foreign key (TASK_EXECUTION_ID)
+ references TASK_EXECUTION(TASK_EXECUTION_ID)
+) ;
diff --git a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/SimpleTaskConfigurationTests.java b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/SimpleTaskConfigurationTests.java
index 8ad62029..9be462b0 100644
--- a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/SimpleTaskConfigurationTests.java
+++ b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/SimpleTaskConfigurationTests.java
@@ -22,10 +22,12 @@ import static org.junit.Assert.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.springframework.aop.framework.Advised;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.cloud.task.configuration.SimpleTaskConfiguration;
-import org.springframework.cloud.task.repository.support.LoggerTaskRepository;
import org.springframework.cloud.task.repository.TaskRepository;
+import org.springframework.cloud.task.repository.support.SimpleTaskRepository;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -35,16 +37,17 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
* @author Glenn Renfro
*/
@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(classes = SimpleTaskConfiguration.class)
+@ContextConfiguration(classes = {SimpleTaskConfiguration.class, PropertyPlaceholderAutoConfiguration.class})
public class SimpleTaskConfigurationTests {
@Autowired
private TaskRepository taskRepository;
@Test
- public void testRepository() {
+ public void testRepository() throws Exception {
assertNotNull("testRepository should not be null", taskRepository);
- assertThat(taskRepository, instanceOf(LoggerTaskRepository.class));
+ TaskRepository clazz = (TaskRepository) ((Advised)taskRepository).getTargetSource().getTarget();
+ assertThat(clazz, instanceOf(SimpleTaskRepository.class));
}
}
diff --git a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/TaskHandlerDefaultTests.java b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/TaskHandlerDefaultTests.java
index 89025747..19a4a6ff 100644
--- a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/TaskHandlerDefaultTests.java
+++ b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/TaskHandlerDefaultTests.java
@@ -23,10 +23,11 @@ import org.aspectj.lang.JoinPoint;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.cloud.task.configuration.TaskHandler;
import org.springframework.cloud.task.repository.TaskExecution;
-import org.springframework.cloud.task.util.LoggerTestUtils;
import org.springframework.cloud.task.util.TestDefaultConfiguration;
+import org.springframework.cloud.task.util.TestVerifierUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -37,7 +38,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
* @author Glenn Renfro
*/
@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(classes = TestDefaultConfiguration.class)
+@ContextConfiguration(classes = {TestDefaultConfiguration.class, PropertyPlaceholderAutoConfiguration.class})
public class TaskHandlerDefaultTests {
@Autowired
@@ -49,9 +50,9 @@ public class TaskHandlerDefaultTests {
@Test
public void testTaskException() {
taskHandler.beforeCommandLineRunner(joinPoint);
- final Appender mockAppender = LoggerTestUtils.getMockAppender();
+ final Appender mockAppender = TestVerifierUtils.getMockAppender();
taskHandler.logExceptionCommandLineRunner(joinPoint);
- LoggerTestUtils.verifyLogEntryExists(mockAppender,
+ TestVerifierUtils.verifyLogEntryExists(mockAppender,
"Updating: TaskExecution{executionId='" +
taskHandler.getTaskExecution().getExecutionId());
TaskExecution taskExecution = taskHandler.getTaskExecution();
@@ -61,9 +62,9 @@ public class TaskHandlerDefaultTests {
@Test
public void testTaskCreate() {
- final Appender mockAppender = LoggerTestUtils.getMockAppender();
+ final Appender mockAppender = TestVerifierUtils.getMockAppender();
taskHandler.beforeCommandLineRunner(joinPoint);
- LoggerTestUtils.verifyLogEntryExists(mockAppender,
+ TestVerifierUtils.verifyLogEntryExists(mockAppender,
"Creating: TaskExecution{executionId='" +
taskHandler.getTaskExecution().getExecutionId());
assertEquals("Create should report that exit code is zero",
@@ -74,9 +75,9 @@ public class TaskHandlerDefaultTests {
@Test
public void testTaskUpdate() {
taskHandler.beforeCommandLineRunner(joinPoint);
- final Appender mockAppender = LoggerTestUtils.getMockAppender();
+ final Appender mockAppender = TestVerifierUtils.getMockAppender();
taskHandler.afterReturnCommandLineRunner(joinPoint);
- LoggerTestUtils.verifyLogEntryExists(mockAppender,
+ TestVerifierUtils.verifyLogEntryExists(mockAppender,
"Updating: TaskExecution{executionId='" +
taskHandler.getTaskExecution().getExecutionId());
assertEquals("Update should report that exit code is zero",
diff --git a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/dao/JdbcTaskExecutionDaoTests.java b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/dao/JdbcTaskExecutionDaoTests.java
new file mode 100644
index 00000000..9624404c
--- /dev/null
+++ b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/dao/JdbcTaskExecutionDaoTests.java
@@ -0,0 +1,101 @@
+/*
+ * 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.repository.dao;
+
+import javax.sql.DataSource;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
+import org.springframework.cloud.task.annotation.EnableTask;
+import org.springframework.cloud.task.repository.TaskExecution;
+import org.springframework.cloud.task.util.TestDBUtils;
+import org.springframework.cloud.task.util.TestVerifierUtils;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.dao.DuplicateKeyException;
+
+/**
+ * Executes unit tests on JdbcTaskExecutionDao.
+ *
+ * @author Glenn Renfro
+ */
+public class JdbcTaskExecutionDaoTests {
+
+ private DataSource dataSource;
+
+ private AnnotationConfigApplicationContext context;
+
+ @Before
+ public void setup() {
+ this.context = new AnnotationConfigApplicationContext();
+ this.context.register(TestConfiguration.class,
+ EmbeddedDataSourceConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class);
+ this.context.refresh();
+ dataSource = this.context.getBean(DataSource.class);
+ }
+
+ @After
+ public void close() {
+ if (this.context != null) {
+ this.context.close();
+ }
+ }
+
+ @Test
+ public void saveTaskExecution() {
+ JdbcTaskExecutionDao dao = new JdbcTaskExecutionDao(dataSource);
+ TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
+ dao.saveTaskExecution(expectedTaskExecution);
+
+ TestVerifierUtils.verifyTaskExecution(expectedTaskExecution,
+ TestDBUtils.getTaskExecutionFromDB(dataSource, expectedTaskExecution.getExecutionId()));
+ }
+
+ @Test(expected = DuplicateKeyException.class)
+ public void duplicateSaveTaskExecution() {
+ JdbcTaskExecutionDao dao = new JdbcTaskExecutionDao(dataSource);
+ TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
+ dao.saveTaskExecution(expectedTaskExecution);
+ dao.saveTaskExecution(expectedTaskExecution);
+ }
+
+ @Test
+ public void updateTaskExecution() {
+ JdbcTaskExecutionDao dao = new JdbcTaskExecutionDao(dataSource);
+
+ TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
+ dao.saveTaskExecution(expectedTaskExecution);
+ dao.updateTaskExecution(expectedTaskExecution);
+ TestVerifierUtils.verifyTaskExecution(expectedTaskExecution,
+ TestDBUtils.getTaskExecutionFromDB(dataSource, expectedTaskExecution.getExecutionId()));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void updateTaskExecutionWithNoCreate() {
+ JdbcTaskExecutionDao dao = new JdbcTaskExecutionDao(dataSource);
+
+ TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
+ dao.updateTaskExecution(expectedTaskExecution);
+ }
+
+ @EnableTask
+ protected static class TestConfiguration {
+ }
+}
diff --git a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/dao/MapTaskExecutionDaoTests.java b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/dao/MapTaskExecutionDaoTests.java
new file mode 100644
index 00000000..a9f00cca
--- /dev/null
+++ b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/dao/MapTaskExecutionDaoTests.java
@@ -0,0 +1,57 @@
+/*
+ * 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.repository.dao;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Map;
+
+import org.junit.Test;
+import org.springframework.cloud.task.repository.TaskExecution;
+import org.springframework.cloud.task.util.TestVerifierUtils;
+
+/**
+ * Executes unit tests on MapTaskExecutionDaoTests.
+ * @author Glenn Renfro
+ */
+public class MapTaskExecutionDaoTests {
+
+
+ @Test
+ public void saveTaskExecution(){
+ MapTaskExecutionDao dao = new MapTaskExecutionDao();
+ TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
+ dao.saveTaskExecution(expectedTaskExecution);
+ Map taskExecutionMap = dao.getTaskExecutions();
+ assertNotNull("taskExecutionMap must not be null", taskExecutionMap);
+ TestVerifierUtils.verifyTaskExecution(expectedTaskExecution,
+ taskExecutionMap.get(expectedTaskExecution.getExecutionId()));
+ }
+
+ @Test
+ public void updateTaskExecution(){
+ MapTaskExecutionDao dao = new MapTaskExecutionDao();
+ TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
+ dao.saveTaskExecution(expectedTaskExecution);
+ dao.updateTaskExecution(expectedTaskExecution);
+ Map taskExecutionMap = dao.getTaskExecutions();
+ assertNotNull("taskExecutionMap must not be null", taskExecutionMap);
+ TestVerifierUtils.verifyTaskExecution(expectedTaskExecution,
+ taskExecutionMap.get(expectedTaskExecution.getExecutionId()));
+ }
+
+}
diff --git a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/DatabaseTypeTests.java b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/DatabaseTypeTests.java
new file mode 100644
index 00000000..388226f9
--- /dev/null
+++ b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/DatabaseTypeTests.java
@@ -0,0 +1,88 @@
+/*
+ * 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.repository.support;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.springframework.cloud.task.repository.support.DatabaseType.HSQL;
+import static org.springframework.cloud.task.repository.support.DatabaseType.ORACLE;
+import static org.springframework.cloud.task.repository.support.DatabaseType.POSTGRES;
+import static org.springframework.cloud.task.repository.support.DatabaseType.fromProductName;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+
+import javax.sql.DataSource;
+
+import org.junit.Test;
+
+/**
+ * Tests that the correct database names are selected from datasource metadata.
+ *
+ * @author Lucas Ward
+ * @author Will Schipp
+ * @author Glenn Renfro
+ *
+ */
+public class DatabaseTypeTests {
+
+ @Test
+ public void testFromProductName() {
+ assertEquals(HSQL, fromProductName("HSQL Database Engine"));
+ assertEquals(ORACLE, fromProductName("Oracle"));
+ assertEquals(POSTGRES, fromProductName("PostgreSQL"));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidProductName() {
+ fromProductName("bad product name");
+ }
+
+ @Test
+ public void testFromMetaDataForHsql() throws Exception {
+ DataSource ds = getMockDataSource("HSQL Database Engine");
+ assertEquals(HSQL, DatabaseType.fromMetaData(ds));
+ }
+
+ @Test
+ public void testFromMetaDataForOracle() throws Exception {
+ DataSource ds = getMockDataSource("Oracle");
+ assertEquals(ORACLE, DatabaseType.fromMetaData(ds));
+ }
+
+ @Test
+ public void testFromMetaDataForPostgres() throws Exception {
+ DataSource ds = getMockDataSource("PostgreSQL");
+ assertEquals(POSTGRES, DatabaseType.fromMetaData(ds));
+ }
+
+ public DataSource getMockDataSource(String databaseProductName) throws Exception {
+ DatabaseMetaData dmd = mock(DatabaseMetaData.class);
+ DataSource ds = mock(DataSource.class);
+ Connection con = mock(Connection.class);
+ when(ds.getConnection()).thenReturn(con);
+ when(con.getMetaData()).thenReturn(dmd);
+ when(dmd.getDatabaseProductName()).thenReturn(databaseProductName);
+ return ds;
+ }
+
+ public DataSource getMockDataSource(Exception e) throws Exception {
+ DataSource ds = mock(DataSource.class);
+ when(ds.getConnection()).thenReturn(null);
+ return ds;
+ }
+}
diff --git a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/SimpleTaskRepositoryJdbcTests.java b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/SimpleTaskRepositoryJdbcTests.java
new file mode 100644
index 00000000..efaafeaa
--- /dev/null
+++ b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/SimpleTaskRepositoryJdbcTests.java
@@ -0,0 +1,101 @@
+/*
+ * 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.repository.support;
+
+import javax.sql.DataSource;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
+import org.springframework.cloud.task.annotation.EnableTask;
+import org.springframework.cloud.task.repository.TaskExecution;
+import org.springframework.cloud.task.repository.TaskRepository;
+import org.springframework.cloud.task.util.TaskExecutionCreator;
+import org.springframework.cloud.task.util.TestDBUtils;
+import org.springframework.cloud.task.util.TestVerifierUtils;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+/**
+ * Tests for the SimpleTaskRepository that uses JDBC as a datastore.
+ *
+ * @author Glenn Renfro.
+ */
+public class SimpleTaskRepositoryJdbcTests {
+
+ private TaskRepository taskRepository;
+
+ private DataSource dataSource;
+
+ private AnnotationConfigApplicationContext context;
+
+ @Before
+ public void setup() {
+ this.context = new AnnotationConfigApplicationContext();
+ this.context.register(TestConfiguration.class,
+ EmbeddedDataSourceConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class);
+ this.context.refresh();
+ dataSource = this.context.getBean(DataSource.class);
+ JdbcTaskRepositoryFactoryBean factoryBean =
+ new JdbcTaskRepositoryFactoryBean(dataSource);
+ taskRepository = factoryBean.getObject();
+ }
+
+ @After
+ public void close() {
+ if (this.context != null) {
+ this.context.close();
+ }
+ }
+
+ @Test
+ public void testCreateTaskExecutionNoParam() {
+ TaskExecution expectedTaskExecution =
+ TaskExecutionCreator.createAndStoreTaskExecutionNoParams(taskRepository);
+ TaskExecution actualTaskExecution = TestDBUtils.getTaskExecutionFromDB(dataSource,
+ expectedTaskExecution.getExecutionId());
+ TestVerifierUtils.verifyTaskExecution(expectedTaskExecution, actualTaskExecution);
+ }
+
+ @Test
+ public void testCreateTaskExecutionWithParam() {
+ TaskExecution expectedTaskExecution =
+ TaskExecutionCreator.createAndStoreTaskExecutionWithParams(taskRepository);
+ TaskExecution actualTaskExecution = TestDBUtils.getTaskExecutionFromDB(
+ dataSource, expectedTaskExecution.getExecutionId());
+ TestVerifierUtils.verifyTaskExecution(expectedTaskExecution, actualTaskExecution);
+ }
+
+ @Test
+ public void testUpdateTaskExecution() {
+ TaskExecution expectedTaskExecution =
+ TaskExecutionCreator.createAndStoreTaskExecutionNoParams(taskRepository);
+ expectedTaskExecution = TaskExecutionCreator.updateTaskExecution(taskRepository,
+ expectedTaskExecution.getExecutionId());
+ TaskExecution actualTaskExecution = TestDBUtils.getTaskExecutionFromDB(
+ dataSource, expectedTaskExecution.getExecutionId());
+ TestVerifierUtils.verifyTaskExecution(expectedTaskExecution, actualTaskExecution);
+ }
+
+ @EnableTask
+ protected static class TestConfiguration {
+ }
+
+}
+
diff --git a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/LoggerTaskRepositoryTests.java b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/SimpleTaskRepositoryLoggerTests.java
similarity index 56%
rename from spring-cloud-task-core/src/test/java/org/springframework/cloud/task/LoggerTaskRepositoryTests.java
rename to spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/SimpleTaskRepositoryLoggerTests.java
index d52505e4..95ad4277 100644
--- a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/LoggerTaskRepositoryTests.java
+++ b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/SimpleTaskRepositoryLoggerTests.java
@@ -14,58 +14,50 @@
* limitations under the License.
*/
-package org.springframework.cloud.task;
-
-import java.util.UUID;
+package org.springframework.cloud.task.repository.support;
import ch.qos.logback.core.Appender;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.task.repository.TaskExecution;
import org.springframework.cloud.task.repository.TaskRepository;
-import org.springframework.cloud.task.util.LoggerTestUtils;
+import org.springframework.cloud.task.util.TaskExecutionCreator;
import org.springframework.cloud.task.util.TestDefaultConfiguration;
+import org.springframework.cloud.task.util.TestVerifierUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
- * Verifies that the LoggerRepository has correct prefixes written to logs.
+ * Verifies that the SimpleTaskRepository has correct prefixes written to logs.
* @author Glenn Renfro
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestDefaultConfiguration.class)
-public class LoggerTaskRepositoryTests {
+public class SimpleTaskRepositoryLoggerTests {
@Autowired
private TaskRepository taskRepository;
- private TaskExecution taskExecution;
-
- private String uuId;
-
- @Before
- public void setup(){
- taskExecution = new TaskExecution();
- uuId = UUID.randomUUID().toString();
- taskExecution.setExecutionId(uuId);
- }
-
@Test
public void testCreateTaskExecution() {
- final Appender mockAppender = LoggerTestUtils.getMockAppender();
- taskRepository.createTaskExecution(taskExecution);
- LoggerTestUtils.verifyLogEntryExists(mockAppender,
- "Creating: TaskExecution{executionId='" + uuId);
+ final Appender mockAppender = TestVerifierUtils.getMockAppender();
+ TaskExecution expectedTaskExecution =
+ TaskExecutionCreator.createAndStoreTaskExecutionNoParams(taskRepository);
+ TestVerifierUtils.verifyLogEntryExists(mockAppender,
+ "Creating: TaskExecution{executionId='" + expectedTaskExecution.getExecutionId());
}
@Test
public void testTaskUpdate() {
- final Appender mockAppender = LoggerTestUtils.getMockAppender();
- taskRepository.update(taskExecution);
- LoggerTestUtils.verifyLogEntryExists(mockAppender,
- "Updating: TaskExecution{executionId='" + uuId);
+ final Appender mockAppender = TestVerifierUtils.getMockAppender();
+ TaskExecution expectedTaskExecution =
+ TaskExecutionCreator.createAndStoreTaskExecutionNoParams(taskRepository);
+ TaskExecutionCreator.updateTaskExecution(taskRepository,
+ expectedTaskExecution.getExecutionId());
+ TestVerifierUtils.verifyLogEntryExists(mockAppender,
+ "Updating: TaskExecution{executionId='"
+ + expectedTaskExecution.getExecutionId());
}
}
diff --git a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/SimpleTaskRepositoryMapTests.java b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/SimpleTaskRepositoryMapTests.java
new file mode 100644
index 00000000..fc54ca6c
--- /dev/null
+++ b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/SimpleTaskRepositoryMapTests.java
@@ -0,0 +1,83 @@
+/*
+ * 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.repository.support;
+
+import static org.springframework.test.util.AssertionErrors.assertTrue;
+
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.cloud.task.repository.TaskExecution;
+import org.springframework.cloud.task.repository.TaskRepository;
+import org.springframework.cloud.task.repository.dao.MapTaskExecutionDao;
+import org.springframework.cloud.task.util.TaskExecutionCreator;
+import org.springframework.cloud.task.util.TestVerifierUtils;
+
+/**
+ * Tests for the SimpleTaskRepository that uses Map as a datastore.
+ * @author Glenn Renfro.
+ */
+public class SimpleTaskRepositoryMapTests {
+
+ private TaskRepository taskRepository;
+
+ @Before
+ public void setUp() {
+ MapTaskRepositoryFactoryBean factoryBean =
+ new MapTaskRepositoryFactoryBean();
+ taskRepository = factoryBean.getObject();
+ }
+
+ @Test
+ public void testCreateTaskExecutionNoParam() {
+ TaskExecution expectedTaskExecution =
+ TaskExecutionCreator.createAndStoreTaskExecutionNoParams(taskRepository);
+ TestVerifierUtils.verifyTaskExecution(expectedTaskExecution,
+ getSingleTaskExecutionFromMapRepository(taskRepository,
+ expectedTaskExecution.getExecutionId()));
+ }
+
+ @Test
+ public void testCreateTaskExecutionWithParam() {
+ TaskExecution expectedTaskExecution =
+ TaskExecutionCreator.createAndStoreTaskExecutionWithParams(taskRepository);
+ TestVerifierUtils.verifyTaskExecution(expectedTaskExecution,
+ getSingleTaskExecutionFromMapRepository(taskRepository,
+ expectedTaskExecution.getExecutionId()));
+ }
+
+ @Test
+ public void testUpdateTaskExecution() {
+ TaskExecution expectedTaskExecution =
+ TaskExecutionCreator.createAndStoreTaskExecutionNoParams(taskRepository);
+ expectedTaskExecution = TaskExecutionCreator.updateTaskExecution(taskRepository,
+ expectedTaskExecution.getExecutionId());
+ TestVerifierUtils.verifyTaskExecution(expectedTaskExecution,
+ getSingleTaskExecutionFromMapRepository(taskRepository,
+ expectedTaskExecution.getExecutionId()));
+ }
+
+ private TaskExecution getSingleTaskExecutionFromMapRepository(
+ TaskRepository repository, String taskExecutionId){
+ Map taskMap = ((MapTaskExecutionDao)
+ ((SimpleTaskRepository)taskRepository).getTaskExecutionDao()).getTaskExecutions();
+ assertTrue("taskExecutionId must be in MapTaskExecutionRepository",
+ taskMap.containsKey(taskExecutionId));
+ return taskMap.get(taskExecutionId);
+ }
+}
diff --git a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/TaskDatabaseInitializerTests.java b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/TaskDatabaseInitializerTests.java
new file mode 100644
index 00000000..4636f9d3
--- /dev/null
+++ b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/TaskDatabaseInitializerTests.java
@@ -0,0 +1,115 @@
+/*
+ * 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.repository.support;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+
+import javax.sql.DataSource;
+
+import org.junit.After;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
+import org.springframework.cloud.task.annotation.EnableTask;
+import org.springframework.cloud.task.configuration.TaskConfigurer;
+import org.springframework.cloud.task.repository.TaskRepository;
+import org.springframework.cloud.task.repository.dao.MapTaskExecutionDao;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+/**
+ * Verifies that task initialization occurs properly.
+ *
+ * @author Glenn Renfro
+ */
+public class TaskDatabaseInitializerTests {
+ private AnnotationConfigApplicationContext context;
+
+ @Rule
+ public ExpectedException expected = ExpectedException.none();
+
+ @After
+ public void close() {
+ if (this.context != null) {
+ this.context.close();
+ }
+ }
+
+ @Test
+ public void testDefaultContext() throws Exception {
+ this.context = new AnnotationConfigApplicationContext();
+ this.context.register( TestConfiguration.class,
+ EmbeddedDataSourceConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class);
+ this.context.refresh();
+ assertEquals(0, new JdbcTemplate(this.context.getBean(DataSource.class))
+ .queryForList("select * from TASK_EXECUTION").size());
+ }
+
+// @Test
+ public void testNoDatabase() throws Exception {
+ SimpleTaskRepository repository = new SimpleTaskRepository(new MapTaskExecutionDao());
+ this.context.refresh();
+ assertThat(repository.getTaskExecutionDao(), instanceOf(MapTaskExecutionDao.class));
+ MapTaskExecutionDao dao = (MapTaskExecutionDao) repository.getTaskExecutionDao();
+ assertEquals(0, dao.getTaskExecutions().size());
+ }
+
+ @Test
+ public void testNoTaskConfiguration() throws Exception {
+ this.context = new AnnotationConfigApplicationContext();
+ this.context.register(EmptyConfiguration.class,
+ EmbeddedDataSourceConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class);
+ this.context.refresh();
+ assertEquals(0, this.context.getBeanNamesForType(SimpleTaskRepository.class).length);
+ }
+
+ @Test(expected = BeanCreationException.class)
+ public void testMultipleDataSourcesContext() throws Exception {
+ this.context = new AnnotationConfigApplicationContext();
+ this.context.register( TestConfiguration.class,
+ EmbeddedDataSourceConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class);
+ DataSource dataSource = mock(DataSource.class);
+ context.getBeanFactory().registerSingleton("mockDataSource", dataSource);
+ this.context.refresh();
+ }
+
+ @EnableTask
+ protected static class TestConfiguration {
+ }
+
+ @EnableTask
+ protected static class TestCustomConfiguration implements TaskConfigurer {
+ @Override
+ public TaskRepository getTaskRepository() {
+ return new SimpleTaskRepository(new MapTaskExecutionDao());
+ }
+ }
+
+ @Configuration
+ protected static class EmptyConfiguration {
+ }
+}
diff --git a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/TaskRepositoryFactoryBeanTests.java b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/TaskRepositoryFactoryBeanTests.java
new file mode 100644
index 00000000..b615fd68
--- /dev/null
+++ b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/repository/support/TaskRepositoryFactoryBeanTests.java
@@ -0,0 +1,57 @@
+/*
+ * 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.repository.support;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+
+import javax.sql.DataSource;
+
+import org.junit.Test;
+import org.springframework.cloud.task.repository.TaskRepository;
+import org.springframework.cloud.task.repository.dao.JdbcTaskExecutionDao;
+import org.springframework.cloud.task.repository.dao.MapTaskExecutionDao;
+
+/**
+ * Tests that the TaskRepositoryFactoryBeans produce the correct repositories.
+ *
+ * @author Glenn Renfro
+ */
+
+public class TaskRepositoryFactoryBeanTests {
+
+ @Test
+ public void testJdbcTaskRepositoryFactoryBean() {
+ DataSource dataSource = mock(DataSource.class);
+ JdbcTaskRepositoryFactoryBean factory = new JdbcTaskRepositoryFactoryBean(dataSource);
+ TaskRepository repository = factory.getObject();
+ assertThat(repository, instanceOf(SimpleTaskRepository.class));
+ assertThat(((SimpleTaskRepository) repository).getTaskExecutionDao(),
+ instanceOf(JdbcTaskExecutionDao.class));
+ }
+
+ @Test
+ public void testMapTaskRepositoryFactoryBean() {
+ MapTaskRepositoryFactoryBean factory = new MapTaskRepositoryFactoryBean();
+ TaskRepository repository = factory.getObject();
+ assertThat(repository, instanceOf(SimpleTaskRepository.class));
+ assertThat(((SimpleTaskRepository) repository).getTaskExecutionDao(),
+ instanceOf(MapTaskExecutionDao.class));
+ }
+
+}
diff --git a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/util/LoggerTestUtils.java b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/util/LoggerTestUtils.java
deleted file mode 100644
index c77dad11..00000000
--- a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/util/LoggerTestUtils.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.util;
-
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import ch.qos.logback.classic.spi.LoggingEvent;
-import ch.qos.logback.core.Appender;
-import org.mockito.ArgumentMatcher;
-import org.slf4j.LoggerFactory;
-
-/**
- * Offers utils to test the log results produced by the code being tested.
- *
- * @author Glenn Renfro
- */
-public class LoggerTestUtils {
-
- /**
- * Creates a mock {@link Appender} to be added to the root logger.
- * @return reference to the mock appender.
- */
- public static Appender getMockAppender(){
- ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
- final Appender mockAppender = mock(Appender.class);
- when(mockAppender.getName()).thenReturn("MOCK");
- root.addAppender(mockAppender);
- return mockAppender;
- }
-
- /**
- * Verifies that the log sample is contained within the content that was written
- * to the mock appender.
- * @param mockAppender The appender that is associated with the test.
- * @param logSample The string to search for in the log entry.
- */
- public static void verifyLogEntryExists(Appender mockAppender, final String logSample){
- verify(mockAppender).doAppend(argThat(new ArgumentMatcher() {
- @Override
- public boolean matches(final Object argument) {
- return ((LoggingEvent)argument).getFormattedMessage().contains(logSample);
- }
- }));
- }
-}
diff --git a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/util/TaskExecutionCreator.java b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/util/TaskExecutionCreator.java
new file mode 100644
index 00000000..20c29141
--- /dev/null
+++ b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/util/TaskExecutionCreator.java
@@ -0,0 +1,74 @@
+/*
+ * 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.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.springframework.cloud.task.repository.TaskExecution;
+import org.springframework.cloud.task.repository.TaskRepository;
+
+/**
+ * Offers ability to create TaskExecutions for the test suite.
+ *
+ * @author Glenn Renfro
+ */
+public class TaskExecutionCreator {
+
+ /**
+ * Creates a sample TaskExecution and stores it in the taskRepository.
+ *
+ * @param taskRepository the taskRepository where the taskExecution should be stored.
+ * @return the taskExecution created.
+ */
+ public static TaskExecution createAndStoreTaskExecutionNoParams(TaskRepository taskRepository) {
+ TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
+ taskRepository.createTaskExecution(expectedTaskExecution);
+ return expectedTaskExecution;
+ }
+
+ /**
+ * Creates a sample TaskExecution and stores it in the taskRepository with params.
+ *
+ * @param taskRepository the taskRepository where the taskExecution should be stored.
+ * @return the taskExecution created.
+ */
+ public static TaskExecution createAndStoreTaskExecutionWithParams(TaskRepository taskRepository) {
+ TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
+ List params = new ArrayList();
+ params.add(UUID.randomUUID().toString());
+ params.add(UUID.randomUUID().toString());
+ expectedTaskExecution.setParameters(params);
+ taskRepository.createTaskExecution(expectedTaskExecution);
+ return expectedTaskExecution;
+ }
+
+ /**
+ * Updates a sample TaskExecution in the taskRepository.
+ *
+ * @param taskRepository the taskRepository where the taskExecution should be updated.
+ * @return the taskExecution created.
+ */
+ public static TaskExecution updateTaskExecution(TaskRepository taskRepository,
+ String taskExecutionId) {
+ TaskExecution expectedTaskExecution = TestVerifierUtils.createSampleTaskExecutionNoParam();
+ expectedTaskExecution.setExecutionId(taskExecutionId);
+ taskRepository.update(expectedTaskExecution);
+ return expectedTaskExecution;
+ }
+}
diff --git a/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/util/TestDBUtils.java b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/util/TestDBUtils.java
new file mode 100644
index 00000000..51eced62
--- /dev/null
+++ b/spring-cloud-task-core/src/test/java/org/springframework/cloud/task/util/TestDBUtils.java
@@ -0,0 +1,88 @@
+/*
+ * 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.util;
+
+import static org.junit.Assert.assertEquals;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.sql.DataSource;
+
+import org.springframework.cloud.task.repository.TaskExecution;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+
+/**
+ * Provides a suite of tools that allow tests the ability to retrieve results from a
+ * relational database.
+ *
+ * @author Glenn Renfro
+ */
+public class TestDBUtils {
+
+ /**
+ * Retrieves the TaskExecution from the datasource
+ *
+ * @param dataSource The datasource from which to retrieve the taskExecution
+ * @param taskExecutionId The id of the task to search .
+ * @return taskExecution
+ */
+ public static TaskExecution getTaskExecutionFromDB(DataSource dataSource,
+ String taskExecutionId) {
+ String sql = "SELECT * FROM TASK_EXECUTION WHERE "
+ + "TASK_EXECUTION_ID = '"
+ + taskExecutionId + "'";
+
+ JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
+ List rows = jdbcTemplate.query(sql, new RowMapper(){
+ @Override
+ public TaskExecution mapRow(ResultSet rs, int rownumber) throws SQLException {
+ TaskExecution taskExecution=new TaskExecution();
+ taskExecution.setExecutionId(rs.getString(1));
+ taskExecution.setStartTime(rs.getTimestamp("START_TIME"));
+ taskExecution.setEndTime(rs.getTimestamp("END_TIME"));
+ taskExecution.setExitCode(rs.getInt("EXIT_CODE"));
+ taskExecution.setExitMessage(rs.getString("EXIT_MESSAGE"));
+ taskExecution.setStatusCode(rs.getString("STATUS_CODE"));
+ taskExecution.setTaskName(rs.getString("TASK_NAME"));
+ return taskExecution;
+ }
+ });
+ assertEquals("only one row should be returned", 1, rows.size());
+ TaskExecution taskExecution = rows.get(0);
+
+ populateParamsToDB(dataSource, taskExecution);
+ return taskExecution;
+ }
+
+ private static void populateParamsToDB(DataSource dataSource, TaskExecution taskExecution) {
+ String sql = "SELECT * FROM TASK_EXECUTION_PARAMS WHERE TASK_EXECUTION_ID = '"
+ + taskExecution.getExecutionId() + "'";
+
+ JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
+ List