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
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user