Skip to content

Conversation

@hosuaby
Copy link

@hosuaby hosuaby commented May 8, 2020

The problem: StepBuilderFactory is very permissive concerning listeners.

Method AbstractTaskletStepBuilder#listener(Object listener) accepts an Object as parameter, and this can lead to wrong step configurations as following:

@Configuration public class BadJobConfig { @Autowired private JobBuilderFactory jobs; @Autowired private StepBuilderFactory steps; @Bean public Job someJob(Step someStep) { return jobs .get("some-job") .start(someStep) .build(); } @Bean public Step someStep() { return steps .get("some-step") .tasklet((contribution, chunkContext) -> null) .listener(new DummyJobExecutionListener()) // mistake! It's job listener, not step listener .build(); } static class DummyJobExecutionListener implements JobExecutionListener { @Override public void beforeJob(JobExecution jobExecution) { } @Override public void afterJob(JobExecution jobExecution) { } } }

As you see DummyJobExecutionListener is a job listener! Not step listener. Code compiles and executes without a single warning. This mis-configuration can lead to long painful hours of debugging, before user will notice that he passed wrong listener.

Solution: add runtime assert that will check that Object listener is a valid step execution listener. We can simply use method StepListenerFactoryBean#isListener.

With this feature, the precedent code will throw an exception during application start-up:

Caused by: java.lang.IllegalArgumentException: Object of type [com.adelean.a2.batch.admin.config.BadJobConfig$DummyJobExecutionListener] is not a valid step listener. It must ether implement StepListener interface or have methods annotated with any of:	- @BeforeStep	- @AfterStep	- @BeforeChunk	- @AfterChunk	- @AfterChunkError	- @BeforeRead	- @AfterRead	- @OnReadError	- @BeforeProcess	- @AfterProcess	- @OnProcessError	- @BeforeWrite	- @AfterWrite	- @OnWriteError	- @OnSkipInRead	- @OnSkipInProcess	- @OnSkipInWrite 
@hosuaby hosuaby force-pushed the feature/checkListeners branch from d7e5bf7 to cb71ecf Compare May 10, 2020 18:58
@hosuaby
Copy link
Author

hosuaby commented May 10, 2020

Works also with XML config:

<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/batch" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/batch  http://www.springframework.org/schema/batch/spring-batch.xsd  http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsd"> <job id="someJob"> <step id="someStep"> <tasklet ref="someTasklet"/> <listeners> <listener ref="dummyJobExecutionListener" /> </listeners> </step> </job> </beans:beans> 
@fmbenhassine fmbenhassine added the status: waiting-for-triage Issues that we did not analyse yet label May 12, 2020
@hosuaby hosuaby force-pushed the feature/checkListeners branch from cb71ecf to b645523 Compare May 13, 2020 08:32
@fmbenhassine fmbenhassine changed the title FEATURE: validate step listeners validate step listeners Nov 9, 2020
@fmbenhassine fmbenhassine added pr-for: bug and removed pr-for: enhancement status: waiting-for-triage Issues that we did not analyse yet labels Nov 17, 2022
@fmbenhassine fmbenhassine added this to the 6.0.0 milestone Oct 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

2 participants