spring-projects / spring-projects/spring-batch
close() called twice for ItemReader and ItemWriter beans implementing ItemStream
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 3k
- Forks
- 2.5k
- Avg merge
- 6d 53m
- Merged PRs (30d)
- 3
Description
Bug description
If an ItemWriter or ItemReader bean is also implementing ItemStream, then its close() method will be invoked twice. First by TaskletStep.close() when the step is complete, then by Spring's DisposableBeanAdapter since close() is inferred as a destroy method.
Some beans cannot handle well the second invocation. For example, StaxEventItemWriter throws a NPE at the second close() call which results in a warning message:
2020-11-11 20:19:55.160 WARN 25948 --- [ main] o.s.b.f.support.DisposableBeanAdapter : Destroy method 'close' on bean with name 'scopedTarget.writer' threw an exception: java.lang.NullPointerException: Cannot invoke "java.io.Writer.flush()" because "this.fWriter" is null
Environment
This is reproducible with Spring Batch 4.3.0 and Spring 5.2.10
Also reproducible with Spring Batch 3.0.10 and Spring 4.3.x
Expected behavior
I would expect that close() is invoked only at step completion by TaskletStep.close() since it's not intended to be a destroy method for the ItemStream implementors.
Also, ItemStream javadoc suggest that close() implementations should support multiple invocations without issues, but for StaxEventItemWriter this is not the case:
/**
* If any resources are needed for the stream to operate they need to be destroyed here. Once this method has been
* called all other methods (except open) may throw an exception.
*/
void close() throws ItemStreamException;
Workarounds exist, such as using @Bean(destroyMethod="") or not declaring the writer as a bean, but to me it looks like that the default behaviours of Spring Batch and Spring are in conflict here.
Minimal Complete Reproducible example
Check https://github.com/tiborsulyan/batch-test for a minimal working example. Juts launch the application and observe the warning message which is the result of the second close() invocation of the StaxEventItemWriter bean
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the warning with the linked minimal example, starting from JobConfiguration.java and the StaxEventItemWriter bean. Trace TaskletStep.close() alongside Spring's DisposableBeanAdapter destroy-method handling. Done means an ItemReader or ItemWriter implementing ItemStream is closed at step completion without a second invocation or warning.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100