-
Notifications
You must be signed in to change notification settings - Fork 309
Closed
Description
Context
- A Spring Batch Job can have multiple
JobExecutionListener
s associated with it. This is done via thelistener()
method inJobBuilderFactory
- When using Spring Batch (via
@EnableBatchProcessing
) and Spring Cloud Task (via@EnableTask
) an auto-configuration bean is instantiated:TaskBatchAutoConfiguration
. - The
TaskBatchAutoConfiguration
creates aTaskBatchExecutionListener
(which is aJobExecutionListener
) that associates the ID of the Spring Batch Job with the ID of the Spring Cloud Task. This also registers it to the Job automatically. - When the Job starts, all the registered
JobExecutionListener
s are executed in the order according to:- Any listeners with the
@Order
interface - The order the listeners are registered in
- Any listeners with the
The issue
- There is no apparent way to control when
TaskBatchExecutionListener
is executed. It does not have an@Order
and is always registered after the listeners manually registered throughlistener
i.e. means it always gets executed last - If a listener that is executed before the
TaskBatchExecutionListener
throws an exception then theTaskBatchExecutionListener
is never executed and the association between Job and Task is never made - Spring Cloud Data Flow then produces an error when clicking on "Job Executions" page because that expected association is missing
Desired behaviour:
A way to make sure the TaskBatchExecutionListener
is always executed first
Attempts to solve
AbstractJob
has aCompositeJobExecutionListener
and a methodregisterJobExecutionListener()
which delegates to theregister()
method in the Composite listener.- The
CompositeJobExecutionListener
is private inAbstractJob
and there is no way to override to instantiate a differentCompositeJobExecutionListener
(i.e. a potential solution would be to create a subclass that performs the desired sorting of theTaskBatchExecutionListener
always being first) - Although nasty, you could, via reflection, change the instance of
CompositeJobExecutionListener
to a subclass but then the listener itself has a private field named listeners which is anOrderedComposite
. This class has default visibility so is not immediately subclass-able either
Workaround
- Autowire in the
TaskBatchExecutionListener
to whicheverConfiguration
class contains code to create theJob
bean - Manually register that listener first
- In this way, when the auto configuration tries to register the same
TaskBatchExecutionListener
later, it is ignored because theOrderedComposite
ignores duplicates
The workaround works fine but shouldn't the framework maybe be registering that listener first? Or allowing a way to control the Order of that auto-created bean?
I only noticed this because SCDF dashboard stopped working and then I had to manually remove the task execution from the database to get it to continue working.
Maybe there is something obvious I am missing...
I have created a very simple example application to demo this behaviour. See SpringBatchTaskJobExecListenerFailsTest
: https://github.com/tomgeraghty3/spring-batch-task-job-listeners
hpoettker