Skip to content

close() called twice for ItemReader and ItemWriter beans implementing ItemStream #3801

Open
@tiborsulyan

Description

@tiborsulyan

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions