Reputation: 15
I am using SpringBatch 3.0.2 and trying to create a job that executes a series of steps (some of them in parallel) using JavaConfig style with annotations and a JobBuilderFactory class. What I want to happen is to start with step1 and when it completes to transition to step2a, step2b, step2c, and step2d which all run in parallel. When all of those steps complete then it should transition to step3. I am struggling with the syntax necessary to create this job
@Bean(name = "SplitFlowJob4")
public Job splitFlowJob4() throws SQLException
{
final Flow flow2b = new FlowBuilder<Flow>("subflow2b").from(step2b()).end();
final Flow flow2c = new FlowBuilder<Flow>("subflow2c").from(step2c()).end();
final Flow flow2d = new FlowBuilder<Flow>("subflow2d").from(step2d()).end();
return jobs.get("SplitFlowJob4").start(step1()).next(step2a()).split(new SimpleAsyncTaskExecutor())
.add(flow2b, flow2c, flow2d).next(step3()).end().build();
}
This does not work as I had intended. This executes step1 and step2a only. I do not see step2b, 2c, 2d or step3.
[INFO ] [main] 2015-02-09 15:28:32,169 org.springframework.batch.core.job.SimpleStepHandler - Executing step: [SplitFlowJobStep1]
[INFO ] [main] 2015-02-09 15:28:32,194 org.springframework.batch.core.job.SimpleStepHandler - Executing step: [SplitFlowJobStep2a]
If I change the syntax and call split from step1, then step1, 2a, 2b, 2c, 2d all execute in parallel instead of just steps 2a, 2b, 2c, 2d.
@Bean(name = "SplitFlowJob5")
public Job splitFlowJob5() throws SQLException
{
final Flow flow2a = new FlowBuilder<Flow>("subflow2a").from(step2a()).end();
final Flow flow2b = new FlowBuilder<Flow>("subflow2b").from(step2b()).end();
final Flow flow2c = new FlowBuilder<Flow>("subflow2c").from(step2c()).end();
final Flow flow2d = new FlowBuilder<Flow>("subflow2d").from(step2d()).end();
return jobs.get("SplitFlowJob5").start(step1()).split(new SimpleAsyncTaskExecutor())
.add(flow2a, flow2b, flow2c, flow2d).next(step3()).end().build();
}
This executes Step1, step2a, step2b, step2c, step2d in parallel.
[INFO ] [SimpleAsyncTaskExecutor-2] 2015-02-09 16:28:36,507 org.springframework.batch.core.job.SimpleStepHandler - Executing step: [SplitFlowJobStep2b]
[INFO ] [SimpleAsyncTaskExecutor-5] 2015-02-09 16:28:36,513 org.springframework.batch.core.job.SimpleStepHandler - Executing step: [SplitFlowJobStep1]
[INFO ] [SimpleAsyncTaskExecutor-3] 2015-02-09 16:28:36,512 org.springframework.batch.core.job.SimpleStepHandler - Executing step: [SplitFlowJobStep2c]
[INFO ] [SimpleAsyncTaskExecutor-4] 2015-02-09 16:28:36,509 org.springframework.batch.core.job.SimpleStepHandler - Executing step: [SplitFlowJobStep2d]
[INFO ] [SimpleAsyncTaskExecutor-1] 2015-02-09 16:28:36,507 org.springframework.batch.core.job.SimpleStepHandler - Executing step: [SplitFlowJobStep2a]
[INFO ] [main] 2015-02-09 16:28:36,615 org.springframework.batch.core.job.SimpleStepHandler - Executing step: [SplitFlowJobStep3]
I am not sure what I am doing wrong, is it possible to create a job like this using the fluent builder api? I have seen other working examples that begin or end with a split, but I haven't seen one that includes a split in the middle of the job.
Upvotes: 1
Views: 2878
Reputation: 21463
There was a bug in Spring Batch's java config with splits that was fixed late last week (BATCH-2346). The fix there addresses both the bug that prevents the first flow in your list from being executed as well as documentation fixes on how to address this very use case.
In short, the following should work with the latest code:
@Bean(name = "SplitFlowJob5")
public Job splitFlowJob5() throws SQLException
{
final Flow flow2a = new FlowBuilder<Flow>("subflow2a").from(step2a()).end();
final Flow flow2b = new FlowBuilder<Flow>("subflow2b").from(step2b()).end();
final Flow flow2c = new FlowBuilder<Flow>("subflow2c").from(step2c()).end();
final Flow flow2d = new FlowBuilder<Flow>("subflow2d").from(step2d()).end();
final Flow splitFlow = new FlowBuilder<Flow>("splitFlow")
.start(flow2a)
.split(new SimpleAsyncTaskExecutor())
.add(flow2b, flow2c, flow2d).build();
return jobs.get("SplitFlowJob5").start(step1())
.next(splitFlow).next(step3()).end().build();
}
Upvotes: 4