Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d7e5bf7

Browse files
committed
FEATURE: validate step listeners
1 parent 10fd371 commit d7e5bf7

File tree

6 files changed

+124
-102
lines changed

6 files changed

+124
-102
lines changed

‎spring-batch-core/src/main/java/org/springframework/batch/core/listener/StepListenerFactoryBean.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
*/
1616
package org.springframework.batch.core.listener;
1717

18+
import java.util.stream.Collectors;
19+
import java.util.stream.Stream;
20+
1821
import org.springframework.batch.core.StepListener;
1922

2023
/**
@@ -23,11 +26,22 @@
2326
*
2427
* @author Lucas Ward
2528
* @author Dan Garrette
29+
* @author Alexei KLENIN
2630
* @since 2.0
2731
* @see AbstractListenerFactoryBean
2832
* @see StepListenerMetaData
2933
*/
3034
public class StepListenerFactoryBean extends AbstractListenerFactoryBean<StepListener> {
35+
private static final String STR_STEP_LISTENER_ANNOTATIONS_LIST = Stream
36+
.of(StepListenerMetaData.values())
37+
.map(StepListenerMetaData::getAnnotation)
38+
.map(Class::getSimpleName)
39+
.map(annotation -> String.format("\t- @%s\n", annotation))
40+
.collect(Collectors.joining());
41+
private static final String ERR_OBJECT_NOT_STEP_LISTENER_TEMPLATE =
42+
"Object of type [%s] is not a valid step listener. " +
43+
"It must ether implement StepListener interface or have methods annotated with any of:\n" +
44+
STR_STEP_LISTENER_ANNOTATIONS_LIST;
3145

3246
@Override
3347
protected ListenerMetaData getMetaDataFromPropertyName(String propertyName) {
@@ -74,4 +88,19 @@ public static StepListener getListener(Object delegate) {
7488
public static boolean isListener(Object delegate) {
7589
return AbstractListenerFactoryBean.isListener(delegate, StepListener.class, StepListenerMetaData.values());
7690
}
91+
92+
/**
93+
* Asserts that {@code delegate} is a valid step listener. If this is not a case, throws an
94+
* {@link IllegalArgumentException} with message detailing the problem. Object is a valid
95+
* step listener is it ether implements interface {@link StepListener} or has any method
96+
* annotated with one of marker annotations.
97+
*
98+
* @param delegate the object to check
99+
*/
100+
public static void assertListener(Object delegate) {
101+
if (!isListener(delegate)) {
102+
throw new IllegalArgumentException(String.format(
103+
ERR_OBJECT_NOT_STEP_LISTENER_TEMPLATE, delegate.getClass().getName()));
104+
}
105+
}
77106
}

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.springframework.batch.core.ChunkListener;
2424
import org.springframework.batch.core.Step;
2525
import org.springframework.batch.core.StepExecutionListener;
26+
import org.springframework.batch.core.StepListener;
2627
import org.springframework.batch.core.annotation.AfterChunk;
2728
import org.springframework.batch.core.annotation.AfterChunkError;
2829
import org.springframework.batch.core.annotation.BeforeChunk;
@@ -47,6 +48,7 @@
4748
* @author Dave Syer
4849
* @author Michael Minella
4950
* @author Mahmoud Ben Hassine
51+
* @author Alexei Klenin
5052
*
5153
* @since 2.2
5254
*
@@ -159,10 +161,9 @@ public B listener(Object listener) {
159161
chunkListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), AfterChunk.class));
160162
chunkListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), AfterChunkError.class));
161163

162-
if(chunkListenerMethods.size() > 0) {
163-
StepListenerFactoryBean factory = new StepListenerFactoryBean();
164-
factory.setDelegate(listener);
165-
this.listener((ChunkListener) factory.getObject());
164+
if (!chunkListenerMethods.isEmpty()) {
165+
StepListener stepListener = StepListenerFactoryBean.getListener(listener);
166+
this.listener((ChunkListener) stepListener);
166167
}
167168

168169
@SuppressWarnings("unchecked")

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

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
* @author Chris Schaefer
9292
* @author Michael Minella
9393
* @author Mahmoud Ben Hassine
94+
* @author Alexei Klenin
9495
*
9596
* @since 2.2
9697
*/
@@ -204,18 +205,14 @@ public SimpleStepBuilder<I, O> listener(Object listener) {
204205
skipListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), OnSkipInProcess.class));
205206
skipListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), OnSkipInWrite.class));
206207

207-
if(skipListenerMethods.size() > 0) {
208-
StepListenerFactoryBean factory = new StepListenerFactoryBean();
209-
factory.setDelegate(listener);
210-
skipListeners.add((SkipListener) factory.getObject());
208+
if (!skipListenerMethods.isEmpty()) {
209+
StepListener stepListener = StepListenerFactoryBean.getListener(listener);
210+
skipListeners.add((SkipListener<I, O>) stepListener);
211211
}
212212

213-
@SuppressWarnings("unchecked")
214-
SimpleStepBuilder<I, O> result = this;
215-
return result;
213+
return this;
216214
}
217215

218-
219216
/**
220217
* Register a skip listener.
221218
*

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

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
*
6565
* @author Dave Syer
6666
* @author Mahmoud Ben Hassine
67+
* @author Alexei Klenin
6768
*
6869
* @since 2.2
6970
*/
@@ -265,7 +266,6 @@ public SimpleStepBuilder<I, O> readerIsTransactionalQueue() {
265266
* @param listener the object that has a method configured with listener annotation
266267
* @return this for fluent chaining
267268
*/
268-
@SuppressWarnings("unchecked")
269269
@Override
270270
public SimpleStepBuilder<I, O> listener(Object listener) {
271271
super.listener(listener);
@@ -281,18 +281,14 @@ public SimpleStepBuilder<I, O> listener(Object listener) {
281281
itemListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), OnProcessError.class));
282282
itemListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), OnWriteError.class));
283283

284-
if(itemListenerMethods.size() > 0) {
285-
StepListenerFactoryBean factory = new StepListenerFactoryBean();
286-
factory.setDelegate(listener);
287-
itemListeners.add((StepListener) factory.getObject());
284+
if (!itemListenerMethods.isEmpty()) {
285+
StepListener stepListener = StepListenerFactoryBean.getListener(listener);
286+
itemListeners.add(stepListener);
288287
}
289288

290-
@SuppressWarnings("unchecked")
291-
SimpleStepBuilder<I, O> result = this;
292-
return result;
289+
return this;
293290
}
294291

295-
296292
/**
297293
* Register an item reader listener.
298294
*

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717

1818
import org.apache.commons.logging.Log;
1919
import org.apache.commons.logging.LogFactory;
20+
2021
import org.springframework.batch.core.Step;
2122
import org.springframework.batch.core.StepExecutionListener;
23+
import org.springframework.batch.core.StepListener;
2224
import org.springframework.batch.core.annotation.AfterStep;
2325
import org.springframework.batch.core.annotation.BeforeStep;
2426
import org.springframework.batch.core.listener.StepListenerFactoryBean;
@@ -40,6 +42,7 @@
4042
*
4143
* @author Dave Syer
4244
* @author Michael Minella
45+
* @author Alexei Klenin
4346
*
4447
* @since 2.2
4548
*/
@@ -91,14 +94,15 @@ public B startLimit(int startLimit) {
9194
* @return this for fluent chaining
9295
*/
9396
public B listener(Object listener) {
97+
StepListenerFactoryBean.assertListener(listener);
98+
9499
Set<Method> stepExecutionListenerMethods = new HashSet<>();
95100
stepExecutionListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), BeforeStep.class));
96101
stepExecutionListenerMethods.addAll(ReflectionUtils.findMethod(listener.getClass(), AfterStep.class));
97102

98-
if(stepExecutionListenerMethods.size() > 0) {
99-
StepListenerFactoryBean factory = new StepListenerFactoryBean();
100-
factory.setDelegate(listener);
101-
properties.addStepExecutionListener((StepExecutionListener) factory.getObject());
103+
if (!stepExecutionListenerMethods.isEmpty()) {
104+
StepListener stepListener = StepListenerFactoryBean.getListener(listener);
105+
properties.addStepExecutionListener((StepExecutionListener) stepListener);
102106
}
103107

104108
@SuppressWarnings("unchecked")

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /