diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java index 916ffab09..dce11d25d 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java @@ -22,6 +22,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.batch.core.configuration.support.AutomaticJobRegistrar; import org.springframework.batch.core.configuration.support.DefaultJobLoader; +import org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor; import org.springframework.batch.core.configuration.support.MapJobRegistry; import org.springframework.batch.core.explore.support.JobExplorerFactoryBean; import org.springframework.batch.core.launch.support.JobOperatorFactoryBean; @@ -61,6 +62,7 @@ class BatchRegistrar implements ImportBeanDefinitionRegistrar { registerJobExplorer(registry, batchAnnotation); registerJobLauncher(registry, batchAnnotation); registerJobRegistry(registry); + registerJobRegistryBeanPostProcessor(registry); registerJobOperator(registry, batchAnnotation); registerAutomaticJobRegistrar(registry, batchAnnotation); watch.stop(); @@ -217,6 +219,19 @@ class BatchRegistrar implements ImportBeanDefinitionRegistrar { registry.registerBeanDefinition("jobRegistry", beanDefinition); } + private void registerJobRegistryBeanPostProcessor(BeanDefinitionRegistry registry) { + if (registry.containsBeanDefinition("jobRegistryBeanPostProcessor")) { + LOGGER.info("Bean jobRegistryBeanPostProcessor already defined in the application context, skipping" + + " the registration of a jobRegistryBeanPostProcessor"); + return; + } + BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder + .genericBeanDefinition(JobRegistryBeanPostProcessor.class); + beanDefinitionBuilder.addPropertyReference("jobRegistry", "jobRegistry"); + + registry.registerBeanDefinition("jobRegistryBeanPostProcessor", beanDefinitionBuilder.getBeanDefinition()); + } + private void registerJobOperator(BeanDefinitionRegistry registry, EnableBatchProcessing batchAnnotation) { if (registry.containsBeanDefinition("jobOperator")) { LOGGER.info("Bean jobOperator already defined in the application context, skipping" diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java index 97bd6fb3c..dfeed20d5 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java @@ -91,6 +91,10 @@ import org.springframework.transaction.PlatformTransactionManager; *
  • a {@link org.springframework.batch.core.launch.JobOperator} (bean name * "jobOperator" of type * {@link org.springframework.batch.core.launch.support.SimpleJobOperator})
  • + *
  • a + * {@link org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor} + * (bean name "jobRegistryBeanPostProcessor" of type + * {@link org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor})
  • * * * If the configuration is specified as modular=true, the context also diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java index dc5a18fdc..c3bdbb6e8 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java @@ -84,6 +84,7 @@ import org.springframework.transaction.annotation.Isolation; *
  • a {@link JobLauncher} named "jobLauncher"
  • *
  • a {@link JobRegistry} named "jobRegistry"
  • *
  • a {@link JobOperator} named "JobOperator"
  • + *
  • a {@link JobRegistryBeanPostProcessor} named "jobRegistryBeanPostProcessor"
  • *
  • a {@link org.springframework.batch.core.scope.StepScope} named "stepScope"
  • *
  • a {@link org.springframework.batch.core.scope.JobScope} named "jobScope"
  • * @@ -208,6 +209,19 @@ public class DefaultBatchConfiguration implements ApplicationContextAware { } } + @Bean + public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor() throws BatchConfigurationException { + JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor = new JobRegistryBeanPostProcessor(); + jobRegistryBeanPostProcessor.setJobRegistry(jobRegistry()); + try { + jobRegistryBeanPostProcessor.afterPropertiesSet(); + return jobRegistryBeanPostProcessor; + } + catch (Exception e) { + throw new BatchConfigurationException("Unable to configure the default job registry BeanPostProcessor", e); + } + } + /* * Getters to customize the configuration of infrastructure beans */ diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/BatchRegistrarTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/BatchRegistrarTests.java index 55797db24..f26b80d3e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/BatchRegistrarTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/BatchRegistrarTests.java @@ -27,6 +27,7 @@ import org.springframework.aop.framework.Advised; import org.springframework.batch.core.DefaultJobKeyGenerator; import org.springframework.batch.core.JobKeyGenerator; import org.springframework.batch.core.configuration.JobRegistry; +import org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor; import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.launch.JobOperator; @@ -78,6 +79,7 @@ class BatchRegistrarTests { Assertions.assertTrue(Mockito.mockingDetails(context.getBean(JobLauncher.class)).isMock()); Assertions.assertTrue(Mockito.mockingDetails(context.getBean(JobRegistry.class)).isMock()); Assertions.assertTrue(Mockito.mockingDetails(context.getBean(JobOperator.class)).isMock()); + Assertions.assertTrue(Mockito.mockingDetails(context.getBean(JobRegistryBeanPostProcessor.class)).isMock()); } @Test @@ -160,6 +162,7 @@ class BatchRegistrarTests { JobExplorer jobExplorer = context.getBean(JobExplorer.class); JobRegistry jobRegistry = context.getBean(JobRegistry.class); JobOperator jobOperator = context.getBean(JobOperator.class); + JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor = context.getBean(JobRegistryBeanPostProcessor.class); // then Assertions.assertNotNull(jobLauncher); @@ -167,6 +170,7 @@ class BatchRegistrarTests { Assertions.assertNotNull(jobExplorer); Assertions.assertNotNull(jobRegistry); Assertions.assertNotNull(jobOperator); + Assertions.assertNotNull(jobRegistryBeanPostProcessor); } @Test @@ -244,6 +248,11 @@ class BatchRegistrarTests { return Mockito.mock(); } + @Bean + public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor() { + return Mockito.mock(); + } + } @Configuration diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/DefaultBatchConfigurationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/DefaultBatchConfigurationTests.java index cad911fc1..6c54df5a9 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/DefaultBatchConfigurationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/DefaultBatchConfigurationTests.java @@ -85,6 +85,9 @@ class DefaultBatchConfigurationTests { Assertions.assertEquals(1, jobRepositories.size()); JobRepository jobRepository = jobRepositories.entrySet().iterator().next().getValue(); Assertions.assertInstanceOf(DummyJobRepository.class, jobRepository); + Map jobRegistryBeanPostProcessorMap = context + .getBeansOfType(JobRegistryBeanPostProcessor.class); + Assertions.assertEquals(1, jobRegistryBeanPostProcessorMap.size()); } @Test @@ -98,6 +101,7 @@ class DefaultBatchConfigurationTests { JobExplorer jobExplorer = context.getBean(JobExplorer.class); JobRegistry jobRegistry = context.getBean(JobRegistry.class); JobOperator jobOperator = context.getBean(JobOperator.class); + JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor = context.getBean(JobRegistryBeanPostProcessor.class); // then Assertions.assertNotNull(jobLauncher); @@ -105,6 +109,7 @@ class DefaultBatchConfigurationTests { Assertions.assertNotNull(jobExplorer); Assertions.assertNotNull(jobRegistry); Assertions.assertNotNull(jobOperator); + Assertions.assertNotNull(jobRegistryBeanPostProcessor); } @Configuration @@ -154,6 +159,13 @@ class DefaultBatchConfigurationTests { return new DummyJobRepository(); } + @Bean + public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor(JobRegistry jobRegistry) { + JobRegistryBeanPostProcessor postProcessor = new JobRegistryBeanPostProcessor(); + postProcessor.setJobRegistry(jobRegistry); + return postProcessor; + } + } } \ No newline at end of file diff --git a/spring-batch-docs/modules/ROOT/pages/job/advanced-meta-data.adoc b/spring-batch-docs/modules/ROOT/pages/job/advanced-meta-data.adoc index 6919c2f34..94fc236f5 100644 --- a/spring-batch-docs/modules/ROOT/pages/job/advanced-meta-data.adoc +++ b/spring-batch-docs/modules/ROOT/pages/job/advanced-meta-data.adoc @@ -222,6 +222,8 @@ example has been given an `id` so that it can be included in child contexts (for example, as a parent bean definition) and cause all jobs created there to also be registered automatically. +As of version 5.1, the `@EnableBatchProcessing` annotation automatically registers a `jobRegistryBeanPostProcessor` bean in the application context. + [[automaticjobregistrar]] === AutomaticJobRegistrar