Skip to content

Commit 04b339b

Browse files
committed
Add BeanCreationException to list of standard failure exceptions
Without this change, when passing an invalid job parameter to a bean that is created internally by Spring Batch will cause a BeanCreationException that is essentially ignored. Due to it being ignored, an infinite loop occurs in processing.
1 parent 1e54018 commit 04b339b

File tree

7 files changed

+158
-21
lines changed

7 files changed

+158
-21
lines changed

spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/MapStepExecutionDao.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public void doWith(Field field) throws IllegalArgumentException, IllegalAccessEx
6262
field.setAccessible(true);
6363
field.set(targetExecution, field.get(sourceExecution));
6464
}
65-
});
65+
}, ReflectionUtils.COPYABLE_FIELDS);
6666
}
6767

6868
@Override

spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/FaultTolerantStepBuilder.java

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,18 @@
1515
*/
1616
package org.springframework.batch.core.step.builder;
1717

18+
import java.lang.reflect.Method;
19+
import java.util.ArrayList;
20+
import java.util.Collection;
21+
import java.util.HashMap;
22+
import java.util.HashSet;
23+
import java.util.LinkedHashSet;
24+
import java.util.List;
25+
import java.util.Map;
26+
import java.util.Set;
27+
28+
import javax.batch.operations.BatchRuntimeException;
29+
1830
import org.springframework.batch.core.ChunkListener;
1931
import org.springframework.batch.core.JobInterruptedException;
2032
import org.springframework.batch.core.SkipListener;
@@ -55,6 +67,7 @@
5567
import org.springframework.batch.repeat.RepeatOperations;
5668
import org.springframework.batch.repeat.support.RepeatTemplate;
5769
import org.springframework.batch.support.ReflectionUtils;
70+
import org.springframework.beans.factory.BeanCreationException;
5871
import org.springframework.classify.BinaryExceptionClassifier;
5972
import org.springframework.classify.Classifier;
6073
import org.springframework.classify.SubclassClassifier;
@@ -73,17 +86,6 @@
7386
import org.springframework.transaction.interceptor.TransactionAttribute;
7487
import org.springframework.util.Assert;
7588

76-
import javax.batch.operations.BatchRuntimeException;
77-
import java.lang.reflect.Method;
78-
import java.util.ArrayList;
79-
import java.util.Collection;
80-
import java.util.HashMap;
81-
import java.util.HashSet;
82-
import java.util.LinkedHashSet;
83-
import java.util.List;
84-
import java.util.Map;
85-
import java.util.Set;
86-
8789
/**
8890
* A step builder for fully fault tolerant chunk-oriented item processing steps. Extends {@link SimpleStepBuilder} with
8991
* additional properties for retry and skip of failed items.
@@ -488,11 +490,11 @@ protected ChunkProcessor<I> createChunkProcessor() {
488490
private void addSpecialExceptions() {
489491
addNonSkippableExceptionIfMissing(SkipLimitExceededException.class, NonSkippableReadException.class,
490492
SkipListenerFailedException.class, SkipPolicyFailedException.class, RetryException.class,
491-
JobInterruptedException.class, Error.class);
493+
JobInterruptedException.class, Error.class, BeanCreationException.class);
492494
addNonRetryableExceptionIfMissing(SkipLimitExceededException.class, NonSkippableReadException.class,
493495
TransactionException.class, FatalStepExecutionException.class, SkipListenerFailedException.class,
494496
SkipPolicyFailedException.class, RetryException.class, JobInterruptedException.class, Error.class,
495-
BatchRuntimeException.class);
497+
BatchRuntimeException.class, BeanCreationException.class);
496498
}
497499

498500
protected void detectStreamInReader() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.core.scope.context;
17+
18+
import org.junit.Test;
19+
import org.springframework.batch.core.BatchStatus;
20+
import org.springframework.batch.core.Job;
21+
import org.springframework.batch.core.JobExecution;
22+
import org.springframework.batch.core.JobParametersBuilder;
23+
import org.springframework.batch.core.launch.JobLauncher;
24+
import org.springframework.context.ApplicationContext;
25+
import org.springframework.context.support.ClassPathXmlApplicationContext;
26+
27+
import static org.junit.Assert.assertEquals;
28+
29+
/**
30+
* @author mminella
31+
*/
32+
public class InteralBeanStepScopeIntegrationTests {
33+
34+
@Test
35+
public void testCommitIntervalJobParameter() throws Exception {
36+
ApplicationContext context = new ClassPathXmlApplicationContext("/org/springframework/batch/core/scope/context/CommitIntervalJobParameter-context.xml");
37+
Job job = context.getBean(Job.class);
38+
JobLauncher launcher = context.getBean(JobLauncher.class);
39+
40+
JobExecution execution = launcher.run(job, new JobParametersBuilder().addLong("commit.interval", 1l).toJobParameters());
41+
42+
assertEquals(BatchStatus.COMPLETED, execution.getStatus());
43+
assertEquals(2, execution.getStepExecutions().iterator().next().getReadCount());
44+
assertEquals(2, execution.getStepExecutions().iterator().next().getWriteCount());
45+
}
46+
47+
@Test
48+
public void testInvalidCommitIntervalJobParameter() throws Exception {
49+
ApplicationContext context = new ClassPathXmlApplicationContext("/org/springframework/batch/core/scope/context/CommitIntervalJobParameter-context.xml");
50+
Job job = context.getBean(Job.class);
51+
JobLauncher launcher = context.getBean(JobLauncher.class);
52+
53+
JobExecution execution = launcher.run(job, new JobParametersBuilder().addLong("commit.intervall", 1l).toJobParameters());
54+
55+
assertEquals(BatchStatus.FAILED, execution.getStatus());
56+
}
57+
}

spring-batch-core/src/test/resources/org/springframework/batch/core/launch/JobLauncherIntegrationTests-context.xml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<beans xmlns="http://www.springframework.org/schema/beans"
33
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4-
xmlns:batch="http://www.springframework.org/schema/batch"
5-
xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.2.xsd
4+
xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
65
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
76

87
<job id="job" xmlns="http://www.springframework.org/schema/batch">

spring-batch-core/src/test/resources/org/springframework/batch/core/scope/AsyncJobScopeIntegrationTests-context.xml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<beans xmlns="http://www.springframework.org/schema/beans"
3-
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
4-
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
54
xsi:schemaLocation="
6-
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
7-
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
8-
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
5+
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
96

107
<bean id="simple" class="org.springframework.batch.core.scope.TestCollaborator" scope="job">
118
<property name="name" value="#{jobExecutionContext[foo]}" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<beans xmlns="http://www.springframework.org/schema/beans"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
5+
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd">
6+
7+
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean"/>
8+
9+
<bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager"/>
10+
11+
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
12+
<property name="jobRepository" ref="jobRepository"/>
13+
</bean>
14+
15+
<job id="basicSkipJob"
16+
xmlns="http://www.springframework.org/schema/batch">
17+
<step id="basicSkipStep" >
18+
<tasklet>
19+
<chunk
20+
reader="reader"
21+
writer="writer"
22+
commit-interval="#{jobParameters['commit.interval']}"
23+
skip-policy="skipPolicy">
24+
</chunk>
25+
</tasklet>
26+
</step>
27+
</job>
28+
29+
<bean id="reader" class="org.springframework.batch.item.support.ListItemReader">
30+
<constructor-arg>
31+
<list>
32+
<value>foo</value>
33+
<value>bar</value>
34+
</list>
35+
</constructor-arg>
36+
</bean>
37+
38+
<bean id="writer" class="org.springframework.batch.item.support.ListItemWriter"/>
39+
40+
<bean id="skipPolicy" class="org.springframework.batch.core.step.skip.AlwaysSkipItemSkipPolicy"/>
41+
42+
</beans>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.item.support;
17+
18+
import org.springframework.batch.item.ItemWriter;
19+
20+
import java.util.ArrayList;
21+
import java.util.List;
22+
23+
/**
24+
* @author mminella
25+
*/
26+
public class ListItemWriter<T> implements ItemWriter<T> {
27+
28+
private List<T> writtenItems = new ArrayList<T>();
29+
30+
@Override
31+
public void write(List<? extends T> items) throws Exception {
32+
for (T item : items) {
33+
writtenItems.add(item);
34+
}
35+
}
36+
37+
public List<? extends T> getWrittenItems() {
38+
return this.writtenItems;
39+
}
40+
}

0 commit comments

Comments
 (0)