SCT-6 Support RDBMS & Map Repositories

* `DefaultTaskConfigurer` returns only one `SimpleTaskRepository` all others have been removed
* `SimpleTaskRepository` can use `JdbcTaskExecutionDao` or a `MapTaskExecutionDao`
* Add `Jdbc` and Map` `TaskRepositoryFactoryBeans` to support the creation of the correct type of `SimpleTaskRepository`
* `TaskDatabaseInitializer` will initialize a database if a datasource is found and if they have not disabled it using the `spring.task.initialize.enable`
* Add tests
* Added Transaction Support
* Re-add the samples to `pom.xml`
* Samples pom skips install and deploy lifecycle targets.
This commit is contained in:
Glenn Renfro
2015-12-01 17:45:57 -05:00
committed by Gunnar Hillert
parent 96fab303ae
commit a9f882f24b
36 changed files with 1738 additions and 153 deletions

View File

@@ -27,6 +27,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
@@ -40,13 +44,12 @@
<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
@@ -58,6 +61,16 @@
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -54,7 +54,7 @@ import org.springframework.context.annotation.Import;
* You will also be able to <code>&#064;Autowired</code> some useful stuff into your context:
*
* <ul>
* <li>a {@link TaskRepository} (bean name "taskRepository").</li>
* <li>a {@link TaskRepository} (bean name "taskRepository").
* </ul>
*
* @author Glenn Renfro

View File

@@ -0,0 +1,4 @@
/**
* Annotations for spring cloud task.
*/
package org.springframework.cloud.task.annotation;

View File

@@ -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:
*
* <ul>
* <li>{@link LoggerTaskRepository} will be the default {@link TaskRepository}.</li>
* <li>{@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}.
* </ul>
*
*
* @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();
}
}
}

View File

@@ -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<DataSource> 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<TaskConfigurer> 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;
}
}

View File

@@ -0,0 +1,4 @@
/**
* Interfaces for configuring Spring Cloud Task and a default implementations.
*/
package org.springframework.cloud.task.configuration;

View File

@@ -0,0 +1,4 @@
/**
* Base package for spring cloud task.
*/
package org.springframework.cloud.task;

View File

@@ -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<String> 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<String> parameters;
public TaskExecution() {
parameters = new ArrayList<>();
}
public TaskExecution(String executionId, int exitCode, String taskName,
Date startTime, Date endTime, String statusCode,
String exitMessage, List<String> 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;
}

View File

@@ -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);
}

View File

@@ -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<String> 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);
}
}

View File

@@ -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<String, TaskExecution> 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<String, TaskExecution> getTaskExecutions(){
return Collections.unmodifiableMap(taskExecutions);
}
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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<String, DatabaseType> dbNameMap;
private final String productName;
private DatabaseType(String productName) {
this.productName = productName;
}
static{
dbNameMap = new HashMap<String, DatabaseType>();
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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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.");
}
}

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,4 @@
/**
* Classes used for setting up and supporting a task repositories.
*/
package org.springframework.cloud.task.repository.support;

View File

@@ -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)
) ;

View File

@@ -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));
}
}

View File

@@ -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",

View File

@@ -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 {
}
}

View File

@@ -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<String, TaskExecution> 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<String, TaskExecution> taskExecutionMap = dao.getTaskExecutions();
assertNotNull("taskExecutionMap must not be null", taskExecutionMap);
TestVerifierUtils.verifyTaskExecution(expectedTaskExecution,
taskExecutionMap.get(expectedTaskExecution.getExecutionId()));
}
}

View File

@@ -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;
}
}

View File

@@ -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 {
}
}

View File

@@ -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());
}
}

View File

@@ -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<String, TaskExecution> taskMap = ((MapTaskExecutionDao)
((SimpleTaskRepository)taskRepository).getTaskExecutionDao()).getTaskExecutions();
assertTrue("taskExecutionId must be in MapTaskExecutionRepository",
taskMap.containsKey(taskExecutionId));
return taskMap.get(taskExecutionId);
}
}

View File

@@ -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 {
}
}

View File

@@ -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));
}
}

View File

@@ -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);
}
}));
}
}

View File

@@ -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<String> params = new ArrayList<String>();
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;
}
}

View File

@@ -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<TaskExecution> rows = jdbcTemplate.query(sql, new RowMapper<TaskExecution>(){
@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<Map<String, Object>> rows = jdbcTemplate.queryForList(sql);
List<String> params = new ArrayList<>();
for (Map row : rows) {
params.add((String) row.get("TASK_PARAM"));
}
taskExecution.setParameters(params);
}
}

View File

@@ -18,8 +18,9 @@ package org.springframework.cloud.task.util;
import org.aspectj.lang.JoinPoint;
import org.springframework.cloud.task.configuration.TaskHandler;
import org.springframework.cloud.task.repository.support.LoggerTaskRepository;
import org.springframework.cloud.task.repository.TaskRepository;
import org.springframework.cloud.task.repository.dao.MapTaskExecutionDao;
import org.springframework.cloud.task.repository.support.SimpleTaskRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -33,7 +34,7 @@ public class TestDefaultConfiguration {
@Bean
public TaskRepository taskRepository(){
return new LoggerTaskRepository();
return new SimpleTaskRepository(new MapTaskExecutionDao());
}
@Bean

View File

@@ -0,0 +1,145 @@
/*
* 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 static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
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 java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.Appender;
import org.mockito.ArgumentMatcher;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.task.repository.TaskExecution;
/**
* Offers utils to test the results produced by the code being tested.
*
* @author Glenn Renfro
*/
public class TestVerifierUtils {
/**
* 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);
}
}));
}
/**
* Creates a fully populated TaskExecution (except params) for testing.
*
* @return
*/
public static TaskExecution createSampleTaskExecutionNoParam() {
Random randomGenerator = new Random();
int exitCode = randomGenerator.nextInt();
Date startTime = new Date();
Date endTime = new Date();
String executionId = UUID.randomUUID().toString();
String taskName = UUID.randomUUID().toString();
String exitMessage = UUID.randomUUID().toString();
String statusCode = UUID.randomUUID().toString().substring(0, 9);
return new TaskExecution(executionId, exitCode, taskName,
startTime, endTime, statusCode,
exitMessage, new ArrayList<String>());
}
/**
* Verifies that all the fields in between the expected and actual are the same;
*
* @param expectedTaskExecution The expected value for the task execution.
* @param actualTaskExecution The actual value for the task execution.
*/
public static void verifyTaskExecution(TaskExecution expectedTaskExecution,
TaskExecution actualTaskExecution) {
assertEquals("taskExecutionId must be equal", expectedTaskExecution.getExecutionId(),
actualTaskExecution.getExecutionId());
assertEquals("startTime must be equal",
expectedTaskExecution.getStartTime(),
actualTaskExecution.getStartTime());
assertEquals("endTime must be equal",
expectedTaskExecution.getEndTime(),
actualTaskExecution.getEndTime());
assertEquals("exitCode must be equal",
expectedTaskExecution.getExitCode(),
actualTaskExecution.getExitCode());
assertEquals("taskName must be equal",
expectedTaskExecution.getTaskName(),
actualTaskExecution.getTaskName());
assertEquals("exitMessage must be equal",
expectedTaskExecution.getExitMessage(),
actualTaskExecution.getExitMessage());
assertEquals("statusCode must be equal",
expectedTaskExecution.getStatusCode(),
actualTaskExecution.getStatusCode());
if (expectedTaskExecution.getParameters() != null) {
assertNotNull("parameters should not be null",
actualTaskExecution.getParameters());
assertEquals("parameters result set count should match expected count",
expectedTaskExecution.getParameters().size(),
actualTaskExecution.getParameters().size());
}
else {
assertNull("parameters should be null", actualTaskExecution.getParameters());
}
Set<String> params = new HashSet<String>();
for (String param : expectedTaskExecution.getParameters()) {
params.add(param);
}
for (String param : actualTaskExecution.getParameters()) {
assertTrue("param must exist in the repository", params.contains(param));
}
}
}

View File

@@ -11,4 +11,24 @@
<artifactId>spring-cloud-task-samples</artifactId>
<build>
<pluginManagement>
<plugins>
<plugin>
<!--skip deploy (this is just a test module) -->
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>