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 0727ca648..419477c58 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 @@ -46,8 +46,6 @@ class BatchRegistrar implements ImportBeanDefinitionRegistrar { private static final Log LOGGER = LogFactory.getLog(BatchRegistrar.class); - private static final String MISSING_BEAN_ERROR_MESSAGE = "Unable to find bean '%s' for attribute %s of annotation %s on class %s"; - private static final String MISSING_ANNOTATION_ERROR_MESSAGE = "EnableBatchProcessing is not present on importing class '%s' as expected"; @Override @@ -88,24 +86,10 @@ class BatchRegistrar implements ImportBeanDefinitionRegistrar { // set mandatory properties String dataSourceRef = batchAnnotation.dataSourceRef(); - if (!registry.containsBeanDefinition(dataSourceRef)) { - String errorMessage = String.format(MISSING_BEAN_ERROR_MESSAGE, dataSourceRef, "dataSourceRef", - batchAnnotation, importingClassName); - throw new IllegalStateException(errorMessage); - } - else { - beanDefinitionBuilder.addPropertyReference("dataSource", dataSourceRef); - } + beanDefinitionBuilder.addPropertyReference("dataSource", dataSourceRef); String transactionManagerRef = batchAnnotation.transactionManagerRef(); - if (!registry.containsBeanDefinition(transactionManagerRef)) { - String errorMessage = String.format(MISSING_BEAN_ERROR_MESSAGE, transactionManagerRef, - "transactionManagerRef", batchAnnotation, importingClassName); - throw new IllegalStateException(errorMessage); - } - else { - beanDefinitionBuilder.addPropertyReference("transactionManager", transactionManagerRef); - } + beanDefinitionBuilder.addPropertyReference("transactionManager", transactionManagerRef); // set optional properties String executionContextSerializerRef = batchAnnotation.executionContextSerializerRef(); @@ -150,14 +134,7 @@ class BatchRegistrar implements ImportBeanDefinitionRegistrar { // set mandatory properties String dataSourceRef = batchAnnotation.dataSourceRef(); - if (!registry.containsBeanDefinition(dataSourceRef)) { - String errorMessage = String.format(MISSING_BEAN_ERROR_MESSAGE, dataSourceRef, "dataSourceRef", - batchAnnotation, importingClassName); - throw new IllegalStateException(errorMessage); - } - else { - beanDefinitionBuilder.addPropertyReference("dataSource", dataSourceRef); - } + beanDefinitionBuilder.addPropertyReference("dataSource", dataSourceRef); // set optional properties String executionContextSerializerRef = batchAnnotation.executionContextSerializerRef(); 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 c1d21e9c8..1b42ef4f1 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 @@ -29,7 +29,11 @@ import org.springframework.batch.core.configuration.JobRegistry; 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.repository.dao.JdbcExecutionContextDao; +import org.springframework.batch.core.repository.dao.JdbcJobExecutionDao; import org.springframework.batch.core.repository.dao.JdbcJobInstanceDao; +import org.springframework.batch.core.repository.dao.JdbcStepExecutionDao; +import org.springframework.beans.factory.BeanCreationException; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -49,9 +53,9 @@ import org.springframework.transaction.interceptor.TransactionInterceptor; class BatchRegistrarTests { @Test - @DisplayName("When no datasource is provided, then an IllegalStateException should be thrown") + @DisplayName("When no datasource is provided, then an BeanCreationException should be thrown") void testMissingDataSource() { - Assertions.assertThrows(IllegalStateException.class, new Executable() { + Assertions.assertThrows(BeanCreationException.class, new Executable() { @Override public void execute() throws Throwable { new AnnotationConfigApplicationContext(JobConfigurationWithoutDataSource.class); @@ -60,9 +64,9 @@ class BatchRegistrarTests { } @Test - @DisplayName("When no transaction manager is provided, then an IllegalStateException should be thrown") + @DisplayName("When no transaction manager is provided, then an BeanCreationException should be thrown") void testMissingTransactionManager() { - Assertions.assertThrows(IllegalStateException.class, new Executable() { + Assertions.assertThrows(BeanCreationException.class, new Executable() { @Override public void execute() throws Throwable { new AnnotationConfigApplicationContext(JobConfigurationWithoutTransactionManager.class); @@ -71,7 +75,7 @@ class BatchRegistrarTests { } @Test - @DisplayName("When cusotm beans are provided, then no new ones should be created") + @DisplayName("When cusotm beans are provided, then default ones should not be used") void testConfigurationWithUserDefinedBeans() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( JobConfigurationWithUserDefinedInfrastrucutreBeans.class); @@ -98,7 +102,58 @@ class BatchRegistrarTests { DataSource dataSource = (DataSource) ReflectionTestUtils.getField(jdbcTemplate, "dataSource"); Assertions.assertEquals(context.getBean(DataSource.class), dataSource); - // TODO assert on other DAOs + JdbcJobExecutionDao jobExecutionDao = (JdbcJobExecutionDao) ReflectionTestUtils.getField(jobRepository, + "jobExecutionDao"); + jdbcTemplate = (JdbcTemplate) ReflectionTestUtils.getField(jobExecutionDao, "jdbcTemplate"); + dataSource = (DataSource) ReflectionTestUtils.getField(jdbcTemplate, "dataSource"); + Assertions.assertEquals(context.getBean(DataSource.class), dataSource); + + JdbcStepExecutionDao stepExecutionDao = (JdbcStepExecutionDao) ReflectionTestUtils.getField(jobRepository, + "stepExecutionDao"); + jdbcTemplate = (JdbcTemplate) ReflectionTestUtils.getField(stepExecutionDao, "jdbcTemplate"); + dataSource = (DataSource) ReflectionTestUtils.getField(jdbcTemplate, "dataSource"); + Assertions.assertEquals(context.getBean(DataSource.class), dataSource); + + JdbcExecutionContextDao executionContextDao = (JdbcExecutionContextDao) ReflectionTestUtils + .getField(jobRepository, "ecDao"); + jdbcTemplate = (JdbcTemplate) ReflectionTestUtils.getField(executionContextDao, "jdbcTemplate"); + dataSource = (DataSource) ReflectionTestUtils.getField(jdbcTemplate, "dataSource"); + Assertions.assertEquals(context.getBean(DataSource.class), dataSource); + + PlatformTransactionManager transactionManager = getTransactionManagerSetOnJobRepository(jobRepository); + Assertions.assertEquals(context.getBean(JdbcTransactionManager.class), transactionManager); + } + + @Test + @DisplayName("When custom bean names are provided, then corresponding beans should be used to configure infrastructure beans") + void testConfigurationWithCustonBeanNames() { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( + JobConfigurationWithCustomBeanNames.class); + + JobRepository jobRepository = context.getBean(JobRepository.class); + JdbcJobInstanceDao jobInstanceDao = (JdbcJobInstanceDao) ReflectionTestUtils.getField(jobRepository, + "jobInstanceDao"); + JdbcTemplate jdbcTemplate = (JdbcTemplate) ReflectionTestUtils.getField(jobInstanceDao, "jdbcTemplate"); + DataSource dataSource = (DataSource) ReflectionTestUtils.getField(jdbcTemplate, "dataSource"); + Assertions.assertEquals(context.getBean(DataSource.class), dataSource); + + JdbcJobExecutionDao jobExecutionDao = (JdbcJobExecutionDao) ReflectionTestUtils.getField(jobRepository, + "jobExecutionDao"); + jdbcTemplate = (JdbcTemplate) ReflectionTestUtils.getField(jobExecutionDao, "jdbcTemplate"); + dataSource = (DataSource) ReflectionTestUtils.getField(jdbcTemplate, "dataSource"); + Assertions.assertEquals(context.getBean(DataSource.class), dataSource); + + JdbcStepExecutionDao stepExecutionDao = (JdbcStepExecutionDao) ReflectionTestUtils.getField(jobRepository, + "stepExecutionDao"); + jdbcTemplate = (JdbcTemplate) ReflectionTestUtils.getField(stepExecutionDao, "jdbcTemplate"); + dataSource = (DataSource) ReflectionTestUtils.getField(jdbcTemplate, "dataSource"); + Assertions.assertEquals(context.getBean(DataSource.class), dataSource); + + JdbcExecutionContextDao executionContextDao = (JdbcExecutionContextDao) ReflectionTestUtils + .getField(jobRepository, "ecDao"); + jdbcTemplate = (JdbcTemplate) ReflectionTestUtils.getField(executionContextDao, "jdbcTemplate"); + dataSource = (DataSource) ReflectionTestUtils.getField(jdbcTemplate, "dataSource"); + Assertions.assertEquals(context.getBean(DataSource.class), dataSource); PlatformTransactionManager transactionManager = getTransactionManagerSetOnJobRepository(jobRepository); Assertions.assertEquals(context.getBean(JdbcTransactionManager.class), transactionManager); @@ -172,6 +227,23 @@ class BatchRegistrarTests { } + @Configuration + @EnableBatchProcessing(dataSourceRef = "batchDataSource", transactionManagerRef = "batchTransactionManager") + public static class JobConfigurationWithCustomBeanNames { + + @Bean + public DataSource batchDataSource() { + return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL) + .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); + } + + @Bean + public JdbcTransactionManager batchTransactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + + } + private PlatformTransactionManager getTransactionManagerSetOnJobRepository(JobRepository jobRepository) { Advised target = (Advised) jobRepository; // proxy created by // AbstractJobRepositoryFactoryBean