Add listener to persist relationship between job and task
This introduces a listener that stores the association between a Spring Batch job and the task it was executed within. Resolves spring-cloud/spring-cloud-task#46 Merge Changes based on code review.
This commit is contained in:
committed by
Glenn Renfro
parent
bb76cef391
commit
7c8fc5f50e
1
pom.xml
1
pom.xml
@@ -70,6 +70,7 @@
|
||||
<module>spring-cloud-task-core</module>
|
||||
<module>spring-cloud-task-samples</module>
|
||||
<module>spring-cloud-task-docs</module>
|
||||
<module>spring-cloud-task-batch</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
|
||||
35
spring-cloud-task-batch/pom.xml
Normal file
35
spring-cloud-task-batch/pom.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<artifactId>spring-cloud-task-parent</artifactId>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>spring-cloud-task-batch</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Spring Cloud Task Batch</name>
|
||||
<description>Module for use when combining Spring Cloud Task with Spring Batch</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-task-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.task.batch.configuration;
|
||||
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cloud.task.batch.listener.TaskBatchExecutionListener;
|
||||
import org.springframework.cloud.task.configuration.EnableTask;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Provides auto configuration for the {@link TaskBatchExecutionListener}.
|
||||
*
|
||||
* @author Michael Minella
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({Job.class, EnableTask.class})
|
||||
public class TaskBatchAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TaskBatchExecutionListenerBeanPostProcessor batchTaskExecutionListenerBeanPostProcessor() {
|
||||
return new TaskBatchExecutionListenerBeanPostProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TaskBatchExecutionListenerFactoryBean taskBatchExecutionListener(ConfigurableApplicationContext context) {
|
||||
return new TaskBatchExecutionListenerFactoryBean(context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.task.batch.configuration;
|
||||
|
||||
import org.springframework.batch.core.job.AbstractJob;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.cloud.task.batch.listener.TaskBatchExecutionListener;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
/**
|
||||
* Injects a configured {@link TaskBatchExecutionListener} into any batch jobs (beans
|
||||
* assignable to {@link AbstractJob}) that are executed within the scope of a task. The
|
||||
* context this is used within is expected to have only one bean of type
|
||||
* {@link TaskBatchExecutionListener}.
|
||||
*
|
||||
* @author Michael Minella
|
||||
*/
|
||||
public class TaskBatchExecutionListenerBeanPostProcessor implements BeanPostProcessor {
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
|
||||
int length = this.applicationContext
|
||||
.getBeanNamesForType(TaskBatchExecutionListener.class).length;
|
||||
|
||||
if(bean instanceof AbstractJob) {
|
||||
if(length != 1) {
|
||||
throw new IllegalStateException("The application context is required to " +
|
||||
"have exactly 1 instance of the TaskBatchExecutionListener but has " +
|
||||
length);
|
||||
}
|
||||
|
||||
((AbstractJob) bean).registerJobExecutionListener(
|
||||
this.applicationContext.getBean(TaskBatchExecutionListener.class));
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.task.batch.configuration;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.cloud.task.batch.listener.TaskBatchExecutionListener;
|
||||
import org.springframework.cloud.task.batch.listener.support.JdbcTaskBatchDao;
|
||||
import org.springframework.cloud.task.batch.listener.support.MapTaskBatchDao;
|
||||
import org.springframework.cloud.task.repository.TaskExplorer;
|
||||
import org.springframework.cloud.task.repository.dao.MapTaskExecutionDao;
|
||||
import org.springframework.cloud.task.repository.support.SimpleTaskExplorer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link FactoryBean} for a {@link TaskBatchExecutionListener}. Provides a jdbc based
|
||||
* listener if there is a {@link DataSource} available. Otherwise, builds a listener that
|
||||
* uses the map based implementation.
|
||||
*
|
||||
* @author Michael Minella
|
||||
*/
|
||||
public class TaskBatchExecutionListenerFactoryBean implements FactoryBean<TaskBatchExecutionListener> {
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
private TaskBatchExecutionListener listener;
|
||||
|
||||
private String dataSourceName;
|
||||
|
||||
/**
|
||||
* @param context the current application context
|
||||
*/
|
||||
public TaskBatchExecutionListenerFactoryBean(ConfigurableApplicationContext context) {
|
||||
Assert.notNull(context, "A ConfigurableApplicationContext is required");
|
||||
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskBatchExecutionListener getObject() throws Exception {
|
||||
if(listener != null){
|
||||
return listener;
|
||||
}
|
||||
if(this.context.getBeanNamesForType(DataSource.class).length == 0) {
|
||||
this.listener = new TaskBatchExecutionListener(getMapTaskBatchDao());
|
||||
}
|
||||
else {
|
||||
DataSource dataSource;
|
||||
|
||||
if(StringUtils.hasText(this.dataSourceName)) {
|
||||
dataSource = (DataSource) this.context.getBean(this.dataSourceName);
|
||||
}
|
||||
else {
|
||||
if(this.context.getBeanNamesForType(DataSource.class).length == 1) {
|
||||
dataSource = this.context.getBean(DataSource.class);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unable to determine what DataSource to use");
|
||||
}
|
||||
}
|
||||
this.listener = new TaskBatchExecutionListener(new JdbcTaskBatchDao(dataSource));
|
||||
}
|
||||
|
||||
return listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return TaskBatchExecutionListener.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setDataSourceName(String dataSourceName) {
|
||||
this.dataSourceName = dataSourceName;
|
||||
}
|
||||
|
||||
private MapTaskBatchDao getMapTaskBatchDao() throws Exception {
|
||||
Field taskExecutionDaoField = ReflectionUtils.findField(SimpleTaskExplorer.class, "taskExecutionDao");
|
||||
taskExecutionDaoField.setAccessible(true);
|
||||
|
||||
MapTaskExecutionDao taskExecutionDao;
|
||||
|
||||
TaskExplorer taskExplorer = this.context.getBean(TaskExplorer.class);
|
||||
|
||||
if(AopUtils.isJdkDynamicProxy(taskExplorer)) {
|
||||
SimpleTaskExplorer dereferencedTaskRepository = (SimpleTaskExplorer) ((Advised) taskExplorer).getTargetSource().getTarget();
|
||||
|
||||
taskExecutionDao =
|
||||
(MapTaskExecutionDao) ReflectionUtils.getField(taskExecutionDaoField, dereferencedTaskRepository);
|
||||
}
|
||||
else {
|
||||
taskExecutionDao =
|
||||
(MapTaskExecutionDao) ReflectionUtils.getField(taskExecutionDaoField, taskExplorer);
|
||||
}
|
||||
|
||||
return new MapTaskBatchDao(taskExecutionDao.getBatchJobAssociations());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.task.batch.listener;
|
||||
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.cloud.task.repository.TaskExecution;
|
||||
|
||||
/**
|
||||
* Maintains the association between a {@link TaskExecution} and a {@link JobExecution}
|
||||
* executed within it.
|
||||
*
|
||||
* @author Michael Minella
|
||||
*/
|
||||
public interface TaskBatchDao {
|
||||
|
||||
/**
|
||||
* Saves the relationship between a task execution and a job execution.
|
||||
*
|
||||
* @param taskExecution task execution
|
||||
* @param jobExecution job execution
|
||||
*/
|
||||
void saveRelationship(TaskExecution taskExecution, JobExecution jobExecution);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.task.batch.listener;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.listener.JobExecutionListenerSupport;
|
||||
import org.springframework.cloud.task.listener.annotation.BeforeTask;
|
||||
import org.springframework.cloud.task.repository.TaskExecution;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Responsible for storing the relationship between a Spring Batch job and the Spring
|
||||
* Cloud task it was executed within.
|
||||
*
|
||||
* @author Michael Minella
|
||||
*/
|
||||
public class TaskBatchExecutionListener extends JobExecutionListenerSupport {
|
||||
|
||||
private TaskExecution taskExecution;
|
||||
|
||||
private TaskBatchDao taskBatchDao;
|
||||
|
||||
private final static Log logger = LogFactory.getLog(TaskBatchExecutionListener.class);
|
||||
|
||||
/**
|
||||
* @param taskBatchDao dao used to persist the relationship. Must not be null
|
||||
*/
|
||||
public TaskBatchExecutionListener(TaskBatchDao taskBatchDao) {
|
||||
Assert.notNull(taskBatchDao, "A TaskBatchDao is required");
|
||||
|
||||
this.taskBatchDao = taskBatchDao;
|
||||
}
|
||||
|
||||
@BeforeTask
|
||||
public void onTaskStartup(TaskExecution taskExecution) {
|
||||
this.taskExecution = taskExecution;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeJob(JobExecution jobExecution) {
|
||||
if(this.taskExecution == null) {
|
||||
logger.warn("This job was executed outside the scope of a task but still used the task listener.");
|
||||
}
|
||||
else {
|
||||
logger.info(String.format("The job execution id %s was run within the task execution %s",
|
||||
jobExecution.getId(),
|
||||
this.taskExecution.getExecutionId()));
|
||||
taskBatchDao.saveRelationship(taskExecution, jobExecution);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.task.batch.listener.support;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.cloud.task.batch.listener.TaskBatchDao;
|
||||
import org.springframework.cloud.task.repository.TaskExecution;
|
||||
import org.springframework.cloud.task.repository.dao.JdbcTaskExecutionDao;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* JDBC based implementation of the {@link TaskBatchDao}. Intended to be used in
|
||||
* conjunction with the JDBC based
|
||||
* {@link org.springframework.cloud.task.repository.TaskRepository}
|
||||
*
|
||||
* @author Michael Minella
|
||||
*/
|
||||
public class JdbcTaskBatchDao implements TaskBatchDao {
|
||||
|
||||
private String tablePrefix = JdbcTaskExecutionDao.DEFAULT_TABLE_PREFIX;
|
||||
|
||||
private static final String INSERT_STATEMENT = "INSERT INTO %PREFIX%TASK_BATCH VALUES(?, ?)";
|
||||
|
||||
private JdbcOperations jdbcTemplate;
|
||||
|
||||
/**
|
||||
* @param dataSource {@link DataSource} where the task batch table resides.
|
||||
*/
|
||||
public JdbcTaskBatchDao(DataSource dataSource) {
|
||||
Assert.notNull(dataSource, "A dataSource is required");
|
||||
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveRelationship(TaskExecution taskExecution, JobExecution jobExecution) {
|
||||
Assert.notNull(taskExecution, "A taskExecution is required");
|
||||
Assert.notNull(jobExecution, "A jobExecution is required");
|
||||
jdbcTemplate.update(getQuery(INSERT_STATEMENT), taskExecution.getExecutionId(), jobExecution.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* The table prefix for the task batch table.
|
||||
*
|
||||
* @param tablePrefix defaults to {@link JdbcTaskExecutionDao#DEFAULT_TABLE_PREFIX}.
|
||||
*/
|
||||
public void setTablePrefix(String tablePrefix) {
|
||||
Assert.notNull(tablePrefix, "Null is not allowed as a tablePrefix (use an empty string if you don't want a prefix at all).");
|
||||
this.tablePrefix = tablePrefix;
|
||||
}
|
||||
|
||||
private String getQuery(String base) {
|
||||
return StringUtils.replace(base, "%PREFIX%", tablePrefix);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.task.batch.listener.support;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.cloud.task.batch.listener.TaskBatchDao;
|
||||
import org.springframework.cloud.task.repository.TaskExecution;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Map implementation of the {@link TaskBatchDao}. <note>This is intended for testing
|
||||
* purposes only!</note>
|
||||
*
|
||||
* @author Michael Minella
|
||||
*/
|
||||
public class MapTaskBatchDao implements TaskBatchDao {
|
||||
|
||||
private Map<Long, Set<Long>> relationships;
|
||||
|
||||
public MapTaskBatchDao(Map<Long, Set<Long>> relationships) {
|
||||
Assert.notNull(relationships, "Relationships must not be null");
|
||||
this.relationships = relationships;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveRelationship(TaskExecution taskExecution, JobExecution jobExecution) {
|
||||
Assert.notNull(taskExecution, "A taskExecution is required");
|
||||
Assert.notNull(jobExecution, "A jobExecution is required");
|
||||
|
||||
if(this.relationships.containsKey(taskExecution.getExecutionId())) {
|
||||
this.relationships.get(taskExecution.getExecutionId()).add(jobExecution.getId());
|
||||
}
|
||||
else {
|
||||
TreeSet<Long> jobExecutionIds = new TreeSet<>();
|
||||
jobExecutionIds.add(jobExecution.getId());
|
||||
|
||||
this.relationships.put(taskExecution.getExecutionId(), jobExecutionIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.cloud.task.batch.configuration.TaskBatchAutoConfiguration
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.task.batch.listener;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.StepContribution;
|
||||
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
|
||||
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
|
||||
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
|
||||
import org.springframework.batch.core.scope.context.ChunkContext;
|
||||
import org.springframework.batch.core.step.tasklet.Tasklet;
|
||||
import org.springframework.batch.repeat.RepeatStatus;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
|
||||
import org.springframework.cloud.task.batch.configuration.TaskBatchAutoConfiguration;
|
||||
import org.springframework.cloud.task.configuration.EnableTask;
|
||||
import org.springframework.cloud.task.repository.TaskExecution;
|
||||
import org.springframework.cloud.task.repository.TaskExplorer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Michael Minella
|
||||
*/
|
||||
public class BatchTaskExecutionListenerTests {
|
||||
|
||||
private ConfigurableApplicationContext applicationContext;
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
if(this.applicationContext != null) {
|
||||
this.applicationContext.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutobuiltDataSource() {
|
||||
this.applicationContext = SpringApplication.run(new Object[] {JobConfiguration.class, PropertyPlaceholderAutoConfiguration.class, EmbeddedDataSourceConfiguration.class, TaskBatchAutoConfiguration.class, BatchAutoConfiguration.class, TaskBatchAutoConfiguration.class}, new String[0]);
|
||||
|
||||
TaskExplorer taskExplorer = this.applicationContext.getBean(TaskExplorer.class);
|
||||
|
||||
Page<TaskExecution> page = taskExplorer.findTaskExecutionsByName("application", new PageRequest(0, 1));
|
||||
|
||||
Set<Long> jobExecutionIds = taskExplorer.getJobExecutionIdsByTaskExecutionId(page.iterator().next().getExecutionId());
|
||||
|
||||
assertEquals(1, jobExecutionIds.size());
|
||||
assertEquals(1, taskExplorer.getTaskExecution(jobExecutionIds.iterator().next()).getExecutionId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutobuiltDataSourceNoJob() {
|
||||
this.applicationContext = SpringApplication.run(new Object[] {NoJobConfiguration.class, PropertyPlaceholderAutoConfiguration.class, EmbeddedDataSourceConfiguration.class, TaskBatchAutoConfiguration.class, BatchAutoConfiguration.class, TaskBatchAutoConfiguration.class}, new String[0]);
|
||||
|
||||
TaskExplorer taskExplorer = this.applicationContext.getBean(TaskExplorer.class);
|
||||
|
||||
Page<TaskExecution> page = taskExplorer.findTaskExecutionsByName("application", new PageRequest(0, 1));
|
||||
|
||||
Set<Long> jobExecutionIds = taskExplorer.getJobExecutionIdsByTaskExecutionId(page.iterator().next().getExecutionId());
|
||||
|
||||
assertEquals(0, jobExecutionIds.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapBased() {
|
||||
this.applicationContext = SpringApplication.run(new Object[] {JobConfiguration.class, PropertyPlaceholderAutoConfiguration.class, BatchAutoConfiguration.class, TaskBatchAutoConfiguration.class}, new String[0]);
|
||||
|
||||
TaskExplorer taskExplorer = this.applicationContext.getBean(TaskExplorer.class);
|
||||
|
||||
Page<TaskExecution> page = taskExplorer.findTaskExecutionsByName("application", new PageRequest(0, 1));
|
||||
|
||||
Set<Long> jobExecutionIds = taskExplorer.getJobExecutionIdsByTaskExecutionId(page.iterator().next().getExecutionId());
|
||||
|
||||
assertEquals(1, jobExecutionIds.size());
|
||||
assertEquals(0, (long) taskExplorer.getTaskExecutionIdByJobExecutionId(jobExecutionIds.iterator().next()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleJobs() {
|
||||
this.applicationContext = SpringApplication.run(new Object[] {MultipleJobConfiguration.class, PropertyPlaceholderAutoConfiguration.class, BatchAutoConfiguration.class, TaskBatchAutoConfiguration.class}, new String[0]);
|
||||
|
||||
TaskExplorer taskExplorer = this.applicationContext.getBean(TaskExplorer.class);
|
||||
|
||||
Page<TaskExecution> page = taskExplorer.findTaskExecutionsByName("application", new PageRequest(0, 1));
|
||||
|
||||
Set<Long> jobExecutionIds = taskExplorer.getJobExecutionIdsByTaskExecutionId(page.iterator().next().getExecutionId());
|
||||
|
||||
assertEquals(2, jobExecutionIds.size());
|
||||
Iterator<Long> jobExecutionIdsIterator = jobExecutionIds.iterator();
|
||||
assertEquals(0, (long) taskExplorer.getTaskExecutionIdByJobExecutionId(jobExecutionIdsIterator.next()));
|
||||
assertEquals(0, (long) taskExplorer.getTaskExecutionIdByJobExecutionId(jobExecutionIdsIterator.next()));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableBatchProcessing
|
||||
@EnableTask
|
||||
public static class NoJobConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableBatchProcessing
|
||||
@EnableTask
|
||||
public static class JobConfiguration {
|
||||
|
||||
@Autowired
|
||||
private JobBuilderFactory jobBuilderFactory;
|
||||
|
||||
@Autowired
|
||||
private StepBuilderFactory stepBuilderFactory;
|
||||
|
||||
@Bean
|
||||
public Job job() {
|
||||
return jobBuilderFactory.get("job")
|
||||
.start(stepBuilderFactory.get("step1").tasklet(new Tasklet() {
|
||||
@Override
|
||||
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
|
||||
System.out.println("Executed");
|
||||
return RepeatStatus.FINISHED;
|
||||
}
|
||||
}).build())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableBatchProcessing
|
||||
@EnableTask
|
||||
public static class MultipleJobConfiguration {
|
||||
|
||||
@Autowired
|
||||
private JobBuilderFactory jobBuilderFactory;
|
||||
|
||||
@Autowired
|
||||
private StepBuilderFactory stepBuilderFactory;
|
||||
|
||||
@Bean
|
||||
public Job job1() {
|
||||
return jobBuilderFactory.get("job1")
|
||||
.start(stepBuilderFactory.get("job1step1").tasklet(new Tasklet() {
|
||||
@Override
|
||||
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
|
||||
System.out.println("Executed job1");
|
||||
return RepeatStatus.FINISHED;
|
||||
}
|
||||
}).build())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Job job2() {
|
||||
return jobBuilderFactory.get("job2")
|
||||
.start(stepBuilderFactory.get("job2step1").tasklet(new Tasklet() {
|
||||
@Override
|
||||
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
|
||||
System.out.println("Executed job2");
|
||||
return RepeatStatus.FINISHED;
|
||||
}
|
||||
}).build())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@
|
||||
<artifactId>spring-cloud-task-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Spring Cloud Task Core</name>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<description>Spring Cloud Task</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.cloud.task.repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -25,6 +26,7 @@ import org.springframework.data.domain.Pageable;
|
||||
* Offers methods that allow users to query the task executions that are available.
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
* @author Michael Minella
|
||||
*/
|
||||
public interface TaskExplorer {
|
||||
|
||||
@@ -34,7 +36,7 @@ public interface TaskExplorer {
|
||||
* @param executionId the task execution id
|
||||
* @return the {@link TaskExecution} with this id, or null if not found
|
||||
*/
|
||||
public TaskExecution getTaskExecution(long executionId);
|
||||
TaskExecution getTaskExecution(long executionId);
|
||||
|
||||
|
||||
/**
|
||||
@@ -44,14 +46,14 @@ public interface TaskExplorer {
|
||||
* @param pageable the constraints for the search
|
||||
* @return the set of running executions for tasks with the specified name
|
||||
*/
|
||||
public Page<TaskExecution> findRunningTaskExecutions(String taskName, Pageable pageable);
|
||||
Page<TaskExecution> findRunningTaskExecutions(String taskName, Pageable pageable);
|
||||
|
||||
/**
|
||||
* Retrieve a list of available task names.
|
||||
*
|
||||
* @return the set of task names that have been executed
|
||||
*/
|
||||
public List<String> getTaskNames();
|
||||
List<String> getTaskNames();
|
||||
|
||||
/**
|
||||
* Get number of executions for a taskName.
|
||||
@@ -59,7 +61,7 @@ public interface TaskExplorer {
|
||||
* @param taskName the name of the task to be searched
|
||||
* @return the number of running tasks that have the taskname specified
|
||||
*/
|
||||
public long getTaskExecutionCountByTaskName(String taskName);
|
||||
long getTaskExecutionCountByTaskName(String taskName);
|
||||
|
||||
/**
|
||||
* Retrieves current number of task executions.
|
||||
@@ -75,7 +77,7 @@ public interface TaskExplorer {
|
||||
* @param pageable the constraints for the search
|
||||
* @return list of task executions
|
||||
*/
|
||||
public Page<TaskExecution> findTaskExecutionsByName(String taskName, Pageable pageable);
|
||||
Page<TaskExecution> findTaskExecutionsByName(String taskName, Pageable pageable);
|
||||
|
||||
/**
|
||||
* Retrieves all the task executions within the pageable constraints sorted by
|
||||
@@ -84,6 +86,23 @@ public interface TaskExplorer {
|
||||
* @param pageable the constraints for the search
|
||||
* @return page containing the results from the search
|
||||
*/
|
||||
public Page<TaskExecution> findAll(Pageable pageable);
|
||||
Page<TaskExecution> findAll(Pageable pageable);
|
||||
|
||||
/**
|
||||
* Returns the id of the TaskExecution that the requested Spring Batch job execution
|
||||
* was executed within the context of. Returns null if none were found.
|
||||
*
|
||||
* @param jobExecutionId the id of the JobExecution
|
||||
* @return the id of the {@link TaskExecution}
|
||||
*/
|
||||
Long getTaskExecutionIdByJobExecutionId(long jobExecutionId);
|
||||
|
||||
/**
|
||||
* Returns a Set of JobExecution ids for the jobs that were executed within the scope
|
||||
* of the requested task.
|
||||
*
|
||||
* @param taskExecutionId id of the {@link TaskExecution}
|
||||
* @return a <code>Set</code> of the ids of the job executions executed within the task.
|
||||
*/
|
||||
Set<Long> getJobExecutionIdsByTaskExecutionId(long taskExecutionId);
|
||||
}
|
||||
|
||||
@@ -20,10 +20,13 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
@@ -31,12 +34,14 @@ import org.springframework.batch.item.database.Order;
|
||||
import org.springframework.cloud.task.repository.TaskExecution;
|
||||
import org.springframework.cloud.task.repository.database.PagingQueryProvider;
|
||||
import org.springframework.cloud.task.repository.database.support.SqlPagingQueryProviderFactoryBean;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.ResultSetExtractor;
|
||||
import org.springframework.jdbc.core.RowCallbackHandler;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
|
||||
@@ -95,7 +100,10 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
|
||||
private static final String FIND_TASK_NAMES = "SELECT distinct TASK_NAME from %PREFIX%EXECUTION order by TASK_NAME";
|
||||
|
||||
private static final String DEFAULT_TABLE_PREFIX = "TASK_";
|
||||
private static final String FIND_TASK_EXECUTION_BY_JOB_EXECUTION_ID = "SELECT TASK_EXECUTION_ID FROM %PREFIX%TASK_BATCH WHERE JOB_EXECUTION_ID = ?";
|
||||
private static final String FIND_JOB_EXECUTION_BY_TASK_EXECUTION_ID = "SELECT JOB_EXECUTION_ID FROM %PREFIX%TASK_BATCH WHERE TASK_EXECUTION_ID = ?";
|
||||
|
||||
public static final String DEFAULT_TABLE_PREFIX = "TASK_";
|
||||
|
||||
private String tablePrefix = DEFAULT_TABLE_PREFIX;
|
||||
|
||||
@@ -241,6 +249,43 @@ public class JdbcTaskExecutionDao implements TaskExecutionDao {
|
||||
return taskIncrementer.nextLongValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getTaskExecutionIdByJobExecutionId(long jobExecutionId) {
|
||||
try {
|
||||
return jdbcTemplate.queryForObject(
|
||||
getQuery(FIND_TASK_EXECUTION_BY_JOB_EXECUTION_ID),
|
||||
new Object[] { jobExecutionId },
|
||||
Long.class);
|
||||
}
|
||||
catch (EmptyResultDataAccessException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> getJobExecutionIdsByTaskExecutionId(long taskExecutionId) {
|
||||
try {
|
||||
return jdbcTemplate.query(
|
||||
getQuery(FIND_JOB_EXECUTION_BY_TASK_EXECUTION_ID),
|
||||
new Object[] {taskExecutionId},
|
||||
new ResultSetExtractor<Set<Long>>() {
|
||||
@Override
|
||||
public Set<Long> extractData(ResultSet resultSet) throws SQLException, DataAccessException {
|
||||
Set<Long> jobExecutionIds = new TreeSet<>();
|
||||
|
||||
while(resultSet.next()) {
|
||||
jobExecutionIds.add(resultSet.getLong("JOB_EXECUTION_ID"));
|
||||
}
|
||||
|
||||
return jobExecutionIds;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (DataAccessException e) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
||||
private Page<TaskExecution> queryForPageableResults(Pageable pageable,
|
||||
String selectClause,
|
||||
String fromClause,
|
||||
|
||||
@@ -42,10 +42,13 @@ public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
|
||||
private ConcurrentMap<Long, TaskExecution> taskExecutions;
|
||||
|
||||
private ConcurrentMap<Long, Set<Long>> batchJobAssociations;
|
||||
|
||||
private final AtomicLong currentId = new AtomicLong(0L);
|
||||
|
||||
public MapTaskExecutionDao() {
|
||||
taskExecutions = new ConcurrentHashMap<>();
|
||||
batchJobAssociations = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -68,7 +71,7 @@ public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
|
||||
@Override
|
||||
public TaskExecution getTaskExecution(long executionId) {
|
||||
return taskExecutions.get(executionId);
|
||||
return taskExecutions.get(executionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -149,6 +152,38 @@ public class MapTaskExecutionDao implements TaskExecutionDao {
|
||||
return currentId.getAndIncrement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getTaskExecutionIdByJobExecutionId(long jobExecutionId) {
|
||||
Long taskId = null;
|
||||
|
||||
found:
|
||||
|
||||
for (Map.Entry<Long, Set<Long>> association : batchJobAssociations.entrySet()) {
|
||||
for (Long curJobExecutionId : association.getValue()) {
|
||||
if(curJobExecutionId.equals(jobExecutionId)) {
|
||||
taskId = association.getKey();
|
||||
break found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return taskId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> getJobExecutionIdsByTaskExecutionId(long taskExecutionId) {
|
||||
if(batchJobAssociations.containsKey(taskExecutionId)) {
|
||||
return Collections.unmodifiableSet(batchJobAssociations.get(taskExecutionId));
|
||||
}
|
||||
else {
|
||||
return new TreeSet<>();
|
||||
}
|
||||
}
|
||||
|
||||
public ConcurrentMap<Long, Set<Long>> getBatchJobAssociations() {
|
||||
return batchJobAssociations;
|
||||
}
|
||||
|
||||
private TreeSet<TaskExecution> getTaskExecutionTreeSet() {
|
||||
return new TreeSet<>(new Comparator<TaskExecution>() {
|
||||
@Override
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.cloud.task.repository.dao;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.cloud.task.repository.TaskExecution;
|
||||
import org.springframework.data.domain.Page;
|
||||
@@ -36,7 +37,7 @@ public interface TaskExecutionDao {
|
||||
* @param taskName the name that associated with the task execution.
|
||||
* @param startTime the time task began.
|
||||
* @param parameters list of key/value pairs that configure the task.
|
||||
* @return A fully qualified {@linkTaskExecution} instance.
|
||||
* @return A fully qualified {@link TaskExecution} instance.
|
||||
*/
|
||||
TaskExecution createTaskExecution( String taskName,
|
||||
Date startTime, List<String> parameters);
|
||||
@@ -105,7 +106,7 @@ public interface TaskExecutionDao {
|
||||
*
|
||||
* @return a list of distinct task names from the task repository..
|
||||
*/
|
||||
public List<String> getTaskNames();
|
||||
List<String> getTaskNames();
|
||||
|
||||
/**
|
||||
* Retrieves all the task executions within the pageable constraints.
|
||||
@@ -113,6 +114,27 @@ public interface TaskExecutionDao {
|
||||
* @return page containing the results from the search
|
||||
*/
|
||||
|
||||
public Page<TaskExecution> findAll(Pageable pageable);
|
||||
Page<TaskExecution> findAll(Pageable pageable);
|
||||
|
||||
/**
|
||||
* Retrieves the next available execution id for a task execution.
|
||||
* @return long containing the executionId.
|
||||
*/
|
||||
long getNextExecutionId();
|
||||
|
||||
/**
|
||||
* Returns the id of the TaskExecution that the requested Spring Batch job execution
|
||||
* was executed within the context of. Returns null if non were found.
|
||||
*
|
||||
* @param jobExecutionId the id of the JobExecution
|
||||
* @return the id of the {@link TaskExecution}
|
||||
*/
|
||||
Long getTaskExecutionIdByJobExecutionId(long jobExecutionId);
|
||||
|
||||
/**
|
||||
* Returns the job execution ids associated with a task execution id.
|
||||
* @param taskExecutionId id of the {@link TaskExecution}
|
||||
* @return a <code>Set</code> of the ids of the job executions executed within the task.
|
||||
*/
|
||||
Set<Long> getJobExecutionIdsByTaskExecutionId(long taskExecutionId);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,6 @@ public class SqlPagingQueryUtils {
|
||||
* Generates WHERE clause for queries that require sub selects.
|
||||
*
|
||||
* @param provider the paging query provider that will provide the base where clause
|
||||
* @return a String for the where clause.
|
||||
*/
|
||||
public static void buildWhereClause( AbstractSqlPagingQueryProvider provider,
|
||||
boolean remainingPageQuery, StringBuilder sql) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.cloud.task.repository.support;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.cloud.task.repository.TaskExecution;
|
||||
import org.springframework.cloud.task.repository.TaskExplorer;
|
||||
@@ -29,8 +30,9 @@ import org.springframework.util.Assert;
|
||||
* TaskExplorer for that gathers task information from a task repository.
|
||||
*
|
||||
* @author Glenn Renfro
|
||||
* @author Michael Minella
|
||||
*/
|
||||
public class SimpleTaskExplorer implements TaskExplorer{
|
||||
public class SimpleTaskExplorer implements TaskExplorer {
|
||||
|
||||
private TaskExecutionDao taskExecutionDao;
|
||||
|
||||
@@ -80,4 +82,14 @@ public class SimpleTaskExplorer implements TaskExplorer{
|
||||
return taskExecutionDao.findAll(pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getTaskExecutionIdByJobExecutionId(long jobExecutionId) {
|
||||
return taskExecutionDao.getTaskExecutionIdByJobExecutionId(jobExecutionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> getJobExecutionIdsByTaskExecutionId(long taskExecutionId) {
|
||||
return taskExecutionDao.getJobExecutionIdsByTaskExecutionId(taskExecutionId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,4 +16,11 @@ CREATE TABLE TASK_EXECUTION_PARAMS (
|
||||
references TASK_EXECUTION(TASK_EXECUTION_ID)
|
||||
) ;
|
||||
|
||||
CREATE TABLE TASK_TASK_BATCH (
|
||||
TASK_EXECUTION_ID BIGINT NOT NULL ,
|
||||
JOB_EXECUTION_ID BIGINT NOT NULL ,
|
||||
constraint TASK_EXEC_BATCH_FK foreign key (TASK_EXECUTION_ID)
|
||||
references TASK_EXECUTION(TASK_EXECUTION_ID)
|
||||
) ;
|
||||
|
||||
CREATE SEQUENCE TASK_SEQ ;
|
||||
|
||||
@@ -16,6 +16,13 @@ CREATE TABLE TASK_EXECUTION_PARAMS (
|
||||
references TASK_EXECUTION(TASK_EXECUTION_ID)
|
||||
) ;
|
||||
|
||||
CREATE TABLE TASK_TASK_BATCH (
|
||||
TASK_EXECUTION_ID BIGINT NOT NULL ,
|
||||
JOB_EXECUTION_ID BIGINT NOT NULL ,
|
||||
constraint TASK_EXEC_BATCH_FK foreign key (TASK_EXECUTION_ID)
|
||||
references TASK_EXECUTION(TASK_EXECUTION_ID)
|
||||
) ;
|
||||
|
||||
CREATE TABLE TASK_SEQ (
|
||||
ID BIGINT IDENTITY
|
||||
);
|
||||
|
||||
@@ -16,6 +16,12 @@ CREATE TABLE TASK_EXECUTION_PARAMS (
|
||||
references TASK_EXECUTION(TASK_EXECUTION_ID)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE TASK_TASK_BATCH (
|
||||
TASK_EXECUTION_ID BIGINT NOT NULL ,
|
||||
JOB_EXECUTION_ID BIGINT NOT NULL ,
|
||||
constraint TASK_EXEC_BATCH_FK foreign key (TASK_EXECUTION_ID)
|
||||
references TASK_EXECUTION(TASK_EXECUTION_ID)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE TASK_SEQ (
|
||||
ID BIGINT NOT NULL,
|
||||
|
||||
@@ -16,4 +16,11 @@ CREATE TABLE TASK_EXECUTION_PARAMS (
|
||||
references TASK_EXECUTION(TASK_EXECUTION_ID)
|
||||
) ;
|
||||
|
||||
CREATE TABLE TASK_TASK_BATCH (
|
||||
TASK_EXECUTION_ID NUMBER NOT NULL ,
|
||||
JOB_EXECUTION_ID NUMBER NOT NULL ,
|
||||
constraint TASK_EXEC_BATCH_FK foreign key (TASK_EXECUTION_ID)
|
||||
references TASK_EXECUTION(TASK_EXECUTION_ID)
|
||||
) ;
|
||||
|
||||
CREATE SEQUENCE TASK_SEQ START WITH 0 MINVALUE 0 MAXVALUE 9223372036854775807 NOCACHE NOCYCLE;
|
||||
@@ -16,4 +16,11 @@ CREATE TABLE TASK_EXECUTION_PARAMS (
|
||||
references TASK_EXECUTION(TASK_EXECUTION_ID)
|
||||
) ;
|
||||
|
||||
CREATE TABLE TASK_TASK_BATCH (
|
||||
TASK_EXECUTION_ID BIGINT NOT NULL ,
|
||||
JOB_EXECUTION_ID BIGINT NOT NULL ,
|
||||
constraint TASK_EXEC_BATCH_FK foreign key (TASK_EXECUTION_ID)
|
||||
references TASK_EXECUTION(TASK_EXECUTION_ID)
|
||||
) ;
|
||||
|
||||
CREATE SEQUENCE TASK_SEQ MAXVALUE 9223372036854775807 NO CYCLE;
|
||||
@@ -15,4 +15,11 @@ CREATE TABLE TASK_EXECUTION_PARAMS (
|
||||
references TASK_EXECUTION(TASK_EXECUTION_ID)
|
||||
) ;
|
||||
|
||||
CREATE TABLE TASK_TASK_BATCH (
|
||||
TASK_EXECUTION_ID BIGINT NOT NULL ,
|
||||
JOB_EXECUTION_ID BIGINT NOT NULL ,
|
||||
constraint TASK_EXEC_BATCH_FK foreign key (TASK_EXECUTION_ID)
|
||||
references TASK_EXECUTION(TASK_EXECUTION_ID)
|
||||
) ;
|
||||
|
||||
CREATE TABLE TASK_SEQ (ID BIGINT IDENTITY);
|
||||
|
||||
BIN
spring-cloud-task-samples/batch-job/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
spring-cloud-task-samples/batch-job/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
1
spring-cloud-task-samples/batch-job/.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
1
spring-cloud-task-samples/batch-job/.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
@@ -0,0 +1 @@
|
||||
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.3/apache-maven-3.3.3-bin.zip
|
||||
26
spring-cloud-task-samples/batch-job/README.adoc
Normal file
26
spring-cloud-task-samples/batch-job/README.adoc
Normal file
@@ -0,0 +1,26 @@
|
||||
= Spring Batch Job Task
|
||||
|
||||
This is a Spring Cloud Task application that executes two simple Spring Batch Jobs.
|
||||
|
||||
== Requirements:
|
||||
|
||||
* Java 7 or Above
|
||||
|
||||
== Classes:
|
||||
|
||||
* BatchJobApplication - the Spring Boot Main Application
|
||||
* JobConfiguration - the configuration for the Spring Batch jobs
|
||||
|
||||
== Build:
|
||||
|
||||
[source,shell,indent=2]
|
||||
----
|
||||
$ mvn clean package
|
||||
----
|
||||
|
||||
== Run:
|
||||
|
||||
[source,shell,indent=2]
|
||||
----
|
||||
$ java -jar target/batch-job-1.0.0.BUILD-SNAPSHOT.jar
|
||||
----
|
||||
233
spring-cloud-task-samples/batch-job/mvnw
vendored
Executable file
233
spring-cloud-task-samples/batch-job/mvnw
vendored
Executable file
@@ -0,0 +1,233 @@
|
||||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you 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.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Maven2 Start Up Batch script
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# M2_HOME - location of maven2's installed home dir
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||
|
||||
if [ -f /etc/mavenrc ] ; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ] ; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false;
|
||||
darwin=false;
|
||||
mingw=false
|
||||
case "`uname`" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true;;
|
||||
Darwin*) darwin=true
|
||||
#
|
||||
# Look for the Apple JDKs first to preserve the existing behaviour, and then look
|
||||
# for the new JDKs provided by Oracle.
|
||||
#
|
||||
if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
|
||||
#
|
||||
# Apple JDKs
|
||||
#
|
||||
export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
|
||||
#
|
||||
# Apple JDKs
|
||||
#
|
||||
export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
|
||||
#
|
||||
# Oracle JDKs
|
||||
#
|
||||
export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
|
||||
#
|
||||
# Apple JDKs
|
||||
#
|
||||
export JAVA_HOME=`/usr/libexec/java_home`
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
if [ -r /etc/gentoo-release ] ; then
|
||||
JAVA_HOME=`java-config --jre-home`
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$M2_HOME" ] ; then
|
||||
## resolve links - $0 may be a link to maven's home
|
||||
PRG="$0"
|
||||
|
||||
# need this for relative symlinks
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG="`dirname "$PRG"`/$link"
|
||||
fi
|
||||
done
|
||||
|
||||
saveddir=`pwd`
|
||||
|
||||
M2_HOME=`dirname "$PRG"`/..
|
||||
|
||||
# make it fully qualified
|
||||
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||
|
||||
cd "$saveddir"
|
||||
# echo Using m2 at $M2_HOME
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||
fi
|
||||
|
||||
# For Migwn, ensure paths are in UNIX format before anything is touched
|
||||
if $mingw ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||
# TODO classpath?
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="`which javac`"
|
||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=`which readlink`
|
||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||
if $darwin ; then
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||
else
|
||||
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||
fi
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ] ; then
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD="`which java`"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set."
|
||||
fi
|
||||
|
||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||
fi
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
local basedir=$(pwd)
|
||||
local wdir=$(pwd)
|
||||
while [ "$wdir" != '/' ] ; do
|
||||
if [ -d "$wdir"/.mvn ] ; then
|
||||
basedir=$wdir
|
||||
break
|
||||
fi
|
||||
wdir=$(cd "$wdir/.."; pwd)
|
||||
done
|
||||
echo "${basedir}"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
echo "$(tr -s '\n' ' ' < "$1")"
|
||||
fi
|
||||
}
|
||||
|
||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
|
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will
|
||||
# work with both Windows and non-Windows executions.
|
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||
export MAVEN_CMD_LINE_ARGS
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} "$@"
|
||||
145
spring-cloud-task-samples/batch-job/mvnw.cmd
vendored
Normal file
145
spring-cloud-task-samples/batch-job/mvnw.cmd
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven2 Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
|
||||
set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar""
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||
|
||||
exit /B %ERROR_CODE%
|
||||
103
spring-cloud-task-samples/batch-job/pom.xml
Normal file
103
spring-cloud-task-samples/batch-job/pom.xml
Normal file
@@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>batch-job</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<description>Spring Cloud Task Batch Example</description>
|
||||
|
||||
<name>batch-job</name>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>1.3.3.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-batch</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-task-core</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-task-batch</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.10.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<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>
|
||||
@@ -0,0 +1,16 @@
|
||||
package demo;
|
||||
|
||||
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.task.configuration.EnableTask;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableTask
|
||||
@EnableBatchProcessing
|
||||
public class BatchJobApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(BatchJobApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package demo.configuration;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.StepContribution;
|
||||
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
|
||||
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
|
||||
import org.springframework.batch.core.scope.context.ChunkContext;
|
||||
import org.springframework.batch.core.step.tasklet.Tasklet;
|
||||
import org.springframework.batch.repeat.RepeatStatus;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author Michael Minella
|
||||
*/
|
||||
@Configuration
|
||||
public class JobConfiguration {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(JobConfiguration.class);
|
||||
|
||||
@Autowired
|
||||
public JobBuilderFactory jobBuilderFactory;
|
||||
|
||||
@Autowired
|
||||
public StepBuilderFactory stepBuilderFactory;
|
||||
|
||||
@Bean
|
||||
public Job job1() {
|
||||
return jobBuilderFactory.get("job1")
|
||||
.start(stepBuilderFactory.get("job1step1")
|
||||
.tasklet(new Tasklet() {
|
||||
@Override
|
||||
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
|
||||
logger.info("Job1 was run");
|
||||
return RepeatStatus.FINISHED;
|
||||
}
|
||||
})
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Job job2() {
|
||||
return jobBuilderFactory.get("job2")
|
||||
.start(stepBuilderFactory.get("job2step1")
|
||||
.tasklet(new Tasklet() {
|
||||
@Override
|
||||
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
|
||||
logger.info("Job2 was run");
|
||||
return RepeatStatus.FINISHED;
|
||||
}
|
||||
})
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
spring.application.name=Demo Batch Job Task
|
||||
@@ -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 demo;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.test.OutputCapture;
|
||||
|
||||
/**
|
||||
* Verifies that the Task Application outputs the correct task log entries.
|
||||
*
|
||||
* @author Michael Minella
|
||||
*/
|
||||
public class BatchJobApplicationTests {
|
||||
|
||||
@Rule
|
||||
public OutputCapture outputCapture = new OutputCapture();
|
||||
|
||||
@Test
|
||||
public void testTimeStampApp() throws Exception {
|
||||
final String JOB_RUN_MESSAGE = " was run";
|
||||
final String CREATE_TASK_MESSAGE = "Creating: TaskExecution{executionId=";
|
||||
final String UPDATE_TASK_MESSAGE = "Updating: TaskExecution with executionId=";
|
||||
final String JOB_ASSOCIATION_MESSAGE = "The job execution id ";
|
||||
|
||||
assertEquals(0, SpringApplication.exit(SpringApplication
|
||||
.run(BatchJobApplication.class)));
|
||||
|
||||
String output = this.outputCapture.toString();
|
||||
assertTrue("Unable to find the timestamp: " + output,
|
||||
output.contains(JOB_RUN_MESSAGE));
|
||||
assertTrue("Test results do not show create task message: " + output,
|
||||
output.contains(CREATE_TASK_MESSAGE));
|
||||
assertTrue("Test results do not show success message: " + output,
|
||||
output.contains(UPDATE_TASK_MESSAGE));
|
||||
|
||||
int i = output.indexOf(JOB_ASSOCIATION_MESSAGE);
|
||||
|
||||
assertTrue("Test results do not show the listener message: " + output,
|
||||
i > 0);
|
||||
|
||||
int j = output.indexOf(JOB_ASSOCIATION_MESSAGE, i + 1);
|
||||
|
||||
assertTrue("Test results do not show the listener message: " + output,
|
||||
j > i);
|
||||
|
||||
|
||||
String taskTitle = "Demo Batch Job Task";
|
||||
Pattern pattern = Pattern.compile(taskTitle);
|
||||
Matcher matcher = pattern.matcher(output);
|
||||
int count = 0;
|
||||
while (matcher.find()) {
|
||||
count++;
|
||||
}
|
||||
assertEquals("The number of task titles did not match expected: ", 3, count);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#
|
||||
# Copyright 2016 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
logging.level.root=DEBUG
|
||||
spring.application.name=Demo Batch Job Task
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
<modules>
|
||||
<module>timestamp</module>
|
||||
<module>batch-job</module>
|
||||
</modules>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
= Timestamp Job
|
||||
= Timestamp Task
|
||||
|
||||
This is a Spring Cloud Task application that logs a timestamp.
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>1.3.2.RELEASE</version>
|
||||
<version>1.3.3.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
||||
@@ -40,6 +40,8 @@ import org.springframework.context.annotation.Bean;
|
||||
@EnableConfigurationProperties({ TimestampTaskProperties.class })
|
||||
public class TaskApplication {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(TaskApplication.class);
|
||||
|
||||
@Bean
|
||||
public TimestampTask timeStampTask() {
|
||||
return new TimestampTask();
|
||||
@@ -53,7 +55,6 @@ public class TaskApplication {
|
||||
* A commandline runner that prints a timestamp.
|
||||
*/
|
||||
public class TimestampTask implements CommandLineRunner {
|
||||
private final Log logger = LogFactory.getLog(TimestampTask.class);
|
||||
|
||||
@Autowired
|
||||
private TimestampTaskProperties config;
|
||||
|
||||
Reference in New Issue
Block a user