diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/AbstractBatchConfiguration.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/AbstractBatchConfiguration.java index ad15f974f..32d09dac2 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/AbstractBatchConfiguration.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/AbstractBatchConfiguration.java @@ -17,6 +17,7 @@ package org.springframework.batch.core.configuration.annotation; import org.springframework.batch.core.configuration.JobRegistry; import org.springframework.batch.core.configuration.support.MapJobRegistry; +import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.scope.StepScope; @@ -70,6 +71,9 @@ public abstract class AbstractBatchConfiguration implements ImportAware { @Bean public abstract JobLauncher jobLauncher() throws Exception; + @Bean + public abstract JobExplorer jobExplorer() throws Exception; + @Bean public JobRegistry jobRegistry() throws Exception { return new MapJobRegistry(); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchConfigurer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchConfigurer.java index e5064d5ab..c0c785bc4 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchConfigurer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchConfigurer.java @@ -15,6 +15,7 @@ */ package org.springframework.batch.core.configuration.annotation; +import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.repository.JobRepository; import org.springframework.transaction.PlatformTransactionManager; @@ -33,4 +34,5 @@ public interface BatchConfigurer { JobLauncher getJobLauncher() throws Exception; + JobExplorer getJobExplorer() throws Exception; } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/DefaultBatchConfigurer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/DefaultBatchConfigurer.java index de057a269..797cabc9f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/DefaultBatchConfigurer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/DefaultBatchConfigurer.java @@ -17,12 +17,9 @@ package org.springframework.batch.core.configuration.annotation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.batch.core.configuration.BatchConfigurationException; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import javax.sql.DataSource; - +import org.springframework.batch.core.explore.JobExplorer; +import org.springframework.batch.core.explore.support.JobExplorerFactoryBean; +import org.springframework.batch.core.explore.support.MapJobExplorerFactoryBean; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.launch.support.SimpleJobLauncher; import org.springframework.batch.core.repository.JobRepository; @@ -31,8 +28,12 @@ import org.springframework.batch.core.repository.support.MapJobRepositoryFactory import org.springframework.batch.support.transaction.ResourcelessTransactionManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.stereotype.Component; import org.springframework.transaction.PlatformTransactionManager; +import javax.annotation.PostConstruct; +import javax.sql.DataSource; + @Component public class DefaultBatchConfigurer implements BatchConfigurer { private static final Log logger = LogFactory.getLog(DefaultBatchConfigurer.class); @@ -41,6 +42,7 @@ public class DefaultBatchConfigurer implements BatchConfigurer { private PlatformTransactionManager transactionManager; private JobRepository jobRepository; private JobLauncher jobLauncher; + private JobExplorer jobExplorer; @Autowired(required = false) public void setDataSource(DataSource dataSource) { @@ -69,6 +71,11 @@ public class DefaultBatchConfigurer implements BatchConfigurer { return jobLauncher; } + @Override + public JobExplorer getJobExplorer() { + return jobExplorer; + } + @PostConstruct public void initialize() throws Exception { if(dataSource == null) { @@ -78,11 +85,20 @@ public class DefaultBatchConfigurer implements BatchConfigurer { this.transactionManager = new ResourcelessTransactionManager(); } - MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean(this.transactionManager); - factory.afterPropertiesSet(); - this.jobRepository = factory.getObject(); + MapJobRepositoryFactoryBean jobRepositoryFactory = new MapJobRepositoryFactoryBean(this.transactionManager); + jobRepositoryFactory.afterPropertiesSet(); + this.jobRepository = jobRepositoryFactory.getObject(); + + MapJobExplorerFactoryBean jobExplorerFactory = new MapJobExplorerFactoryBean(jobRepositoryFactory); + jobExplorerFactory.afterPropertiesSet(); + this.jobExplorer = jobExplorerFactory.getObject(); } else { this.jobRepository = createJobRepository(); + + JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean(); + jobExplorerFactoryBean.setDataSource(this.dataSource); + jobExplorerFactoryBean.afterPropertiesSet(); + this.jobExplorer = jobExplorerFactoryBean.getObject(); } this.jobLauncher = createJobLauncher(); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/ModularBatchConfiguration.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/ModularBatchConfiguration.java index 1d5217946..f2b809eeb 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/ModularBatchConfiguration.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/ModularBatchConfiguration.java @@ -15,11 +15,10 @@ */ package org.springframework.batch.core.configuration.annotation; -import java.util.Collection; - import org.springframework.batch.core.configuration.support.ApplicationContextFactory; import org.springframework.batch.core.configuration.support.AutomaticJobRegistrar; import org.springframework.batch.core.configuration.support.DefaultJobLoader; +import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.repository.JobRepository; import org.springframework.beans.factory.annotation.Autowired; @@ -28,6 +27,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; +import java.util.Collection; + /** * Base {@code Configuration} class providing common structure for enabling and using Spring Batch. Customization is * available by implementing the {@link BatchConfigurer} interface. @@ -65,6 +66,12 @@ public class ModularBatchConfiguration extends AbstractBatchConfiguration { return getConfigurer(configurers).getTransactionManager(); } + @Override + @Bean + public JobExplorer jobExplorer() throws Exception { + return getConfigurer(configurers).getJobExplorer(); + } + @Bean public AutomaticJobRegistrar jobRegistrar() throws Exception { registrar.setJobLoader(new DefaultJobLoader(jobRegistry())); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/SimpleBatchConfiguration.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/SimpleBatchConfiguration.java index b3310a267..615b55431 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/SimpleBatchConfiguration.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/SimpleBatchConfiguration.java @@ -15,14 +15,13 @@ */ package org.springframework.batch.core.configuration.annotation; -import java.util.concurrent.atomic.AtomicReference; - import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.target.AbstractLazyCreationTargetSource; import org.springframework.batch.core.configuration.JobRegistry; import org.springframework.batch.core.configuration.support.MapJobRegistry; +import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.repository.JobRepository; import org.springframework.beans.factory.annotation.Autowired; @@ -31,6 +30,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; +import java.util.concurrent.atomic.AtomicReference; + /** * Base {@code Configuration} class providing common structure for enabling and using Spring Batch. Customization is * available by implementing the {@link BatchConfigurer} interface. The main components are created as lazy proxies that @@ -58,6 +59,8 @@ public class SimpleBatchConfiguration extends AbstractBatchConfiguration { private AtomicReference transactionManager = new AtomicReference(); + private AtomicReference jobExplorer = new AtomicReference(); + @Override @Bean public JobRepository jobRepository() throws Exception { @@ -76,6 +79,12 @@ public class SimpleBatchConfiguration extends AbstractBatchConfiguration { return createLazyProxy(jobRegistry, JobRegistry.class); } + @Override + @Bean + public JobExplorer jobExplorer() { + return createLazyProxy(jobExplorer, JobExplorer.class); + } + @Override @Bean public PlatformTransactionManager transactionManager() throws Exception { @@ -107,6 +116,7 @@ public class SimpleBatchConfiguration extends AbstractBatchConfiguration { jobLauncher.set(configurer.getJobLauncher()); transactionManager.set(configurer.getTransactionManager()); jobRegistry.set(new MapJobRegistry()); + jobExplorer.set(configurer.getJobExplorer()); initialized = true; } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/DataSourceConfiguration.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/DataSourceConfiguration.java index cb55c5607..e39c3ce12 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/DataSourceConfiguration.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/DataSourceConfiguration.java @@ -15,10 +15,6 @@ */ package org.springframework.batch.core.configuration.annotation; -import javax.annotation.PostConstruct; -import javax.sql.DataSource; - -import org.springframework.batch.core.PooledEmbeddedDataSource; import org.springframework.batch.core.Step; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; @@ -30,6 +26,9 @@ import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; import org.springframework.util.ClassUtils; +import javax.annotation.PostConstruct; +import javax.sql.DataSource; + @Configuration public class DataSourceConfiguration { @@ -49,7 +48,7 @@ public class DataSourceConfiguration { @Bean public DataSource dataSource() { - return new PooledEmbeddedDataSource(new EmbeddedDatabaseFactory().getDatabase()); + return new EmbeddedDatabaseFactory().getDatabase(); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobLoaderConfigurationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobLoaderConfigurationTests.java index 34d0e0ac4..2e1f801ec 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobLoaderConfigurationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobLoaderConfigurationTests.java @@ -15,10 +15,6 @@ */ package org.springframework.batch.core.configuration.annotation; -import static org.junit.Assert.assertEquals; - -import javax.annotation.PostConstruct; - import org.junit.Test; import org.springframework.batch.core.BatchStatus; import org.springframework.batch.core.Job; @@ -30,6 +26,7 @@ import org.springframework.batch.core.configuration.JobLocator; import org.springframework.batch.core.configuration.support.ApplicationContextFactory; import org.springframework.batch.core.configuration.support.AutomaticJobRegistrar; import org.springframework.batch.core.configuration.support.GenericApplicationContextFactory; +import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.job.builder.SimpleJobBuilder; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.scope.context.ChunkContext; @@ -40,6 +37,10 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import javax.annotation.PostConstruct; + +import static org.junit.Assert.assertEquals; + /** * @author Dave Syer * @@ -72,6 +73,8 @@ public class JobLoaderConfigurationTests { .toJobParameters()); assertEquals(status, execution.getStatus()); assertEquals(stepExecutionCount, execution.getStepExecutions().size()); + JobExplorer jobExplorer = context.getBean(JobExplorer.class); + assertEquals(1, jobExplorer.getJobInstanceCount(jobName)); context.close(); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/MapJobRepositoryConfigurationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/MapJobRepositoryConfigurationTests.java index e7aaf36cc..d085d4807 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/MapJobRepositoryConfigurationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/MapJobRepositoryConfigurationTests.java @@ -23,6 +23,7 @@ import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.PooledEmbeddedDataSource; import org.springframework.batch.core.Step; import org.springframework.batch.core.StepContribution; +import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.scope.context.ChunkContext; @@ -44,6 +45,7 @@ public class MapJobRepositoryConfigurationTests { JobLauncher jobLauncher; JobRepository jobRepository; Job job; + JobExplorer jobExplorer; @Test public void testRoseyScenario() throws Exception { @@ -65,11 +67,13 @@ public class MapJobRepositoryConfigurationTests { this.jobLauncher = context.getBean(JobLauncher.class); this.jobRepository = context.getBean(JobRepository.class); this.job = context.getBean(Job.class); + this.jobExplorer = context.getBean(JobExplorer.class); JobExecution jobExecution = jobLauncher.run(job, new JobParameters()); assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); JobExecution repositoryJobExecution = jobRepository.getLastJobExecution(job.getName(), new JobParameters()); assertEquals(jobExecution.getId(), repositoryJobExecution.getId()); + assertEquals("job", jobExplorer.getJobNames().iterator().next()); context.close(); }