spring-projects / spring-projects/spring-batch

Conditional Flow does not work as stated in official documentation

Open
#4,153 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

has: votes related-to: flow-definition status: need-help-to-reproduce status: waiting-for-reporter type: bug
Dominant language
Java
Stars
3k
Forks
2.5k
Avg merge
6d 53m
Merged PRs (30d)
3

Description

The conditional flow does not work as stated in the official documentation (https://docs.spring.io/spring-batch/docs/current/reference/html/step.html#controllingStepFlow)

Tried with:
Spring Boot: 2.6.7 >> <spring-batch.version>4.3.5</spring-batch.version> >> Java8
Spring Boot: 2.6.9 >> <spring-batch.version>4.3.6</spring-batch.version> >> Java8

@Bean
public Job job() {
	return this.jobBuilderFactory.get("job")
				.start(stepA())
				.on("*").to(stepB())
				.from(stepA()).on("FAILED").to(stepC())
				.end()
				.build();
}

If I use the above example, then:

stepA() is completed successfully then it runs ok to stepB() >> as expected
stepA() fails then step stepB() is executed >> expected stepC() to be executed but instead it was again stepB()

If I reverse the order:

@Bean
public Job job() {
	return this.jobBuilderFactory.get("job")
				.start(stepA())
                                 .on("FAILED").to(stepC())
				.from(stepA()).on("*").to(stepB())
				.end()
				.build();
}

Then I get the following results:

stepA() is completed successfully then it throws Flow execution ended unexpectedly ... Next state not found in flow=... for state=job.step0 with exit status=COMPLETED
stepA() fails then step stepC() is executed >> as expected

The above code was to simplify the explanation, I have attached the example I used. I simulated FAILURE in the first step by throwing an error from FirstItemReader.

Could this be a regression of https://github.com/spring-projects/spring-batch/issues/3638

Also, what is the difference between, is the latter a valid Flow syntax?:

@Bean
public Job job() {
	return this.jobBuilderFactory.get("job")
				.start(stepA()).on("*").to(stepB())
				.from(stepA()).on("FAILED").to(stepC())
				.end()
				.build();
}

and:

@Bean
public Job job() {
	return this.jobBuilderFactory.get("job")
				.start(stepA()).on("*").to(stepB()).end();
				.start(stepA()).on("FAILED").to(stepC()).end()
				.build();
}

Thank you

spring-batch-demo.zip

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the conditional flow section of the linked Spring Batch documentation and reproduce the two job definitions using the attached spring-batch-demo.zip, including the simulated FirstItemReader failure. Compare the behavior with issue 3638 and existing flow tests or entry points before deciding whether the fix belongs in the implementation or documentation. Done means the documented syntax and both success and failure paths behave consistently.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring, spring-boot
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.