Skip to content

Commit aaf22e1

Browse files
committed
Remove bean reference checks in BatchRegistrar
These checks occur too early in the bean creation/registration process and might cause issues when initializing the context. Related to #3942
1 parent 48e437a commit aaf22e1

File tree

2 files changed

+81
-32
lines changed

2 files changed

+81
-32
lines changed

spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/BatchRegistrar.java

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ class BatchRegistrar implements ImportBeanDefinitionRegistrar {
4646

4747
private static final Log LOGGER = LogFactory.getLog(BatchRegistrar.class);
4848

49-
private static final String MISSING_BEAN_ERROR_MESSAGE = "Unable to find bean '%s' for attribute %s of annotation %s on class %s";
50-
5149
private static final String MISSING_ANNOTATION_ERROR_MESSAGE = "EnableBatchProcessing is not present on importing class '%s' as expected";
5250

5351
@Override
@@ -88,24 +86,10 @@ private void registerJobRepository(BeanDefinitionRegistry registry, EnableBatchP
8886

8987
// set mandatory properties
9088
String dataSourceRef = batchAnnotation.dataSourceRef();
91-
if (!registry.containsBeanDefinition(dataSourceRef)) {
92-
String errorMessage = String.format(MISSING_BEAN_ERROR_MESSAGE, dataSourceRef, "dataSourceRef",
93-
batchAnnotation, importingClassName);
94-
throw new IllegalStateException(errorMessage);
95-
}
96-
else {
97-
beanDefinitionBuilder.addPropertyReference("dataSource", dataSourceRef);
98-
}
89+
beanDefinitionBuilder.addPropertyReference("dataSource", dataSourceRef);
9990

10091
String transactionManagerRef = batchAnnotation.transactionManagerRef();
101-
if (!registry.containsBeanDefinition(transactionManagerRef)) {
102-
String errorMessage = String.format(MISSING_BEAN_ERROR_MESSAGE, transactionManagerRef,
103-
"transactionManagerRef", batchAnnotation, importingClassName);
104-
throw new IllegalStateException(errorMessage);
105-
}
106-
else {
107-
beanDefinitionBuilder.addPropertyReference("transactionManager", transactionManagerRef);
108-
}
92+
beanDefinitionBuilder.addPropertyReference("transactionManager", transactionManagerRef);
10993

11094
// set optional properties
11195
String executionContextSerializerRef = batchAnnotation.executionContextSerializerRef();
@@ -150,14 +134,7 @@ private void registerJobExplorer(BeanDefinitionRegistry registry, EnableBatchPro
150134

151135
// set mandatory properties
152136
String dataSourceRef = batchAnnotation.dataSourceRef();
153-
if (!registry.containsBeanDefinition(dataSourceRef)) {
154-
String errorMessage = String.format(MISSING_BEAN_ERROR_MESSAGE, dataSourceRef, "dataSourceRef",
155-
batchAnnotation, importingClassName);
156-
throw new IllegalStateException(errorMessage);
157-
}
158-
else {
159-
beanDefinitionBuilder.addPropertyReference("dataSource", dataSourceRef);
160-
}
137+
beanDefinitionBuilder.addPropertyReference("dataSource", dataSourceRef);
161138

162139
// set optional properties
163140
String executionContextSerializerRef = batchAnnotation.executionContextSerializerRef();

spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/BatchRegistrarTests.java

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@
2929
import org.springframework.batch.core.explore.JobExplorer;
3030
import org.springframework.batch.core.launch.JobLauncher;
3131
import org.springframework.batch.core.repository.JobRepository;
32+
import org.springframework.batch.core.repository.dao.JdbcExecutionContextDao;
33+
import org.springframework.batch.core.repository.dao.JdbcJobExecutionDao;
3234
import org.springframework.batch.core.repository.dao.JdbcJobInstanceDao;
35+
import org.springframework.batch.core.repository.dao.JdbcStepExecutionDao;
36+
import org.springframework.beans.factory.BeanCreationException;
3337
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
3438
import org.springframework.context.annotation.Bean;
3539
import org.springframework.context.annotation.Configuration;
@@ -49,9 +53,9 @@
4953
class BatchRegistrarTests {
5054

5155
@Test
52-
@DisplayName("When no datasource is provided, then an IllegalStateException should be thrown")
56+
@DisplayName("When no datasource is provided, then an BeanCreationException should be thrown")
5357
void testMissingDataSource() {
54-
Assertions.assertThrows(IllegalStateException.class, new Executable() {
58+
Assertions.assertThrows(BeanCreationException.class, new Executable() {
5559
@Override
5660
public void execute() throws Throwable {
5761
new AnnotationConfigApplicationContext(JobConfigurationWithoutDataSource.class);
@@ -60,9 +64,9 @@ public void execute() throws Throwable {
6064
}
6165

6266
@Test
63-
@DisplayName("When no transaction manager is provided, then an IllegalStateException should be thrown")
67+
@DisplayName("When no transaction manager is provided, then an BeanCreationException should be thrown")
6468
void testMissingTransactionManager() {
65-
Assertions.assertThrows(IllegalStateException.class, new Executable() {
69+
Assertions.assertThrows(BeanCreationException.class, new Executable() {
6670
@Override
6771
public void execute() throws Throwable {
6872
new AnnotationConfigApplicationContext(JobConfigurationWithoutTransactionManager.class);
@@ -71,7 +75,7 @@ public void execute() throws Throwable {
7175
}
7276

7377
@Test
74-
@DisplayName("When cusotm beans are provided, then no new ones should be created")
78+
@DisplayName("When cusotm beans are provided, then default ones should not be used")
7579
void testConfigurationWithUserDefinedBeans() {
7680
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
7781
JobConfigurationWithUserDefinedInfrastrucutreBeans.class);
@@ -98,7 +102,58 @@ void testDataSourceAndTransactionManagerSetup() {
98102
DataSource dataSource = (DataSource) ReflectionTestUtils.getField(jdbcTemplate, "dataSource");
99103
Assertions.assertEquals(context.getBean(DataSource.class), dataSource);
100104

101-
// TODO assert on other DAOs
105+
JdbcJobExecutionDao jobExecutionDao = (JdbcJobExecutionDao) ReflectionTestUtils.getField(jobRepository,
106+
"jobExecutionDao");
107+
jdbcTemplate = (JdbcTemplate) ReflectionTestUtils.getField(jobExecutionDao, "jdbcTemplate");
108+
dataSource = (DataSource) ReflectionTestUtils.getField(jdbcTemplate, "dataSource");
109+
Assertions.assertEquals(context.getBean(DataSource.class), dataSource);
110+
111+
JdbcStepExecutionDao stepExecutionDao = (JdbcStepExecutionDao) ReflectionTestUtils.getField(jobRepository,
112+
"stepExecutionDao");
113+
jdbcTemplate = (JdbcTemplate) ReflectionTestUtils.getField(stepExecutionDao, "jdbcTemplate");
114+
dataSource = (DataSource) ReflectionTestUtils.getField(jdbcTemplate, "dataSource");
115+
Assertions.assertEquals(context.getBean(DataSource.class), dataSource);
116+
117+
JdbcExecutionContextDao executionContextDao = (JdbcExecutionContextDao) ReflectionTestUtils
118+
.getField(jobRepository, "ecDao");
119+
jdbcTemplate = (JdbcTemplate) ReflectionTestUtils.getField(executionContextDao, "jdbcTemplate");
120+
dataSource = (DataSource) ReflectionTestUtils.getField(jdbcTemplate, "dataSource");
121+
Assertions.assertEquals(context.getBean(DataSource.class), dataSource);
122+
123+
PlatformTransactionManager transactionManager = getTransactionManagerSetOnJobRepository(jobRepository);
124+
Assertions.assertEquals(context.getBean(JdbcTransactionManager.class), transactionManager);
125+
}
126+
127+
@Test
128+
@DisplayName("When custom bean names are provided, then corresponding beans should be used to configure infrastructure beans")
129+
void testConfigurationWithCustonBeanNames() {
130+
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
131+
JobConfigurationWithCustomBeanNames.class);
132+
133+
JobRepository jobRepository = context.getBean(JobRepository.class);
134+
JdbcJobInstanceDao jobInstanceDao = (JdbcJobInstanceDao) ReflectionTestUtils.getField(jobRepository,
135+
"jobInstanceDao");
136+
JdbcTemplate jdbcTemplate = (JdbcTemplate) ReflectionTestUtils.getField(jobInstanceDao, "jdbcTemplate");
137+
DataSource dataSource = (DataSource) ReflectionTestUtils.getField(jdbcTemplate, "dataSource");
138+
Assertions.assertEquals(context.getBean(DataSource.class), dataSource);
139+
140+
JdbcJobExecutionDao jobExecutionDao = (JdbcJobExecutionDao) ReflectionTestUtils.getField(jobRepository,
141+
"jobExecutionDao");
142+
jdbcTemplate = (JdbcTemplate) ReflectionTestUtils.getField(jobExecutionDao, "jdbcTemplate");
143+
dataSource = (DataSource) ReflectionTestUtils.getField(jdbcTemplate, "dataSource");
144+
Assertions.assertEquals(context.getBean(DataSource.class), dataSource);
145+
146+
JdbcStepExecutionDao stepExecutionDao = (JdbcStepExecutionDao) ReflectionTestUtils.getField(jobRepository,
147+
"stepExecutionDao");
148+
jdbcTemplate = (JdbcTemplate) ReflectionTestUtils.getField(stepExecutionDao, "jdbcTemplate");
149+
dataSource = (DataSource) ReflectionTestUtils.getField(jdbcTemplate, "dataSource");
150+
Assertions.assertEquals(context.getBean(DataSource.class), dataSource);
151+
152+
JdbcExecutionContextDao executionContextDao = (JdbcExecutionContextDao) ReflectionTestUtils
153+
.getField(jobRepository, "ecDao");
154+
jdbcTemplate = (JdbcTemplate) ReflectionTestUtils.getField(executionContextDao, "jdbcTemplate");
155+
dataSource = (DataSource) ReflectionTestUtils.getField(jdbcTemplate, "dataSource");
156+
Assertions.assertEquals(context.getBean(DataSource.class), dataSource);
102157

103158
PlatformTransactionManager transactionManager = getTransactionManagerSetOnJobRepository(jobRepository);
104159
Assertions.assertEquals(context.getBean(JdbcTransactionManager.class), transactionManager);
@@ -172,6 +227,23 @@ public JdbcTransactionManager transactionManager(DataSource dataSource) {
172227

173228
}
174229

230+
@Configuration
231+
@EnableBatchProcessing(dataSourceRef = "batchDataSource", transactionManagerRef = "batchTransactionManager")
232+
public static class JobConfigurationWithCustomBeanNames {
233+
234+
@Bean
235+
public DataSource batchDataSource() {
236+
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL)
237+
.addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build();
238+
}
239+
240+
@Bean
241+
public JdbcTransactionManager batchTransactionManager(DataSource dataSource) {
242+
return new JdbcTransactionManager(dataSource);
243+
}
244+
245+
}
246+
175247
private PlatformTransactionManager getTransactionManagerSetOnJobRepository(JobRepository jobRepository) {
176248
Advised target = (Advised) jobRepository; // proxy created by
177249
// AbstractJobRepositoryFactoryBean

0 commit comments

Comments
 (0)