Using JBeret I execute a simple job with single chunk based step which reads entries from the database, processes them and updates it. The step also defines a ChunkListener which interacts with the database as well and a list of skippable exception classes.
An example of such a job is:
<job id="testJob" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0">
<step id="test">
<listeners>
<listener ref="someChunkListener"/>
</listeners>
<chunk item-count="1" >
<reader ref="testReader" />
<processor ref="testProcessor"/>
<writer ref="testWriter"/>
<skippable-exception-classes>
<include class="java.lang.IllegalStateException"/>
</skippable-exception-classes>
</chunk>
</step>
</job>
I have observed the following flow:
- Transaction has been started for the chunk
- The
someChunkListenerbeforeChunkis triggered - The
ItemReaderis triggered - The
ItemProcessoris triggered - *The
ItemWriteris triggered causing anIllegalStateException - *The
someChunkListenerbeforeChunkis triggered - The
ItemReaderis triggered on new chunk - ...
What I found strange is that between step 5) and step 6) no new transaction is started, but a new chunk has started/the chunk has restarted.
I tried looking into the JSR-352 specification, but I could not find such behavior described. I looked at the pseudo codes provided there, but I could not find a single pseudo code which suggests that a new chunk may be started (beforeChunk on the chunk listener may be called) but the old transaction is used. I also looked at the JBeret implementation of ChunkRunner and it seems that the prevention of starting of a new transaction is intentional.
To me it seems natural that in this situation either no beforeChunk callback would be called (we continue in the same chunk) or a new transaction would exist for our chunk.
I'm worried that I cannot find a well specified transaction boundaries on chunk based jobs. How should I handle possible dirty transactions based on partially written items or updates from the chunk listeners or even sending a JMS messages via XA Transaction?
Is this behavior JBeret behavior described somewhere along with other similar behavior? Is it a bug, or something JSR-352 specific I didn't look at?
I think what you are seeing may have to do with the item-count = 1 in your job xml file. Since every single item has its own chunk, so a new chunk is started after skipping, hence calling the beforeChunk listener method.
Also because in the first chunk, the skippable exception caused the item to be skipped. As a result, there is nothing left to be committed, and active transaction continues onto the next iteration.
See Jakarta Batch spec skippable exception section.
This batch spec issue may be somewhat related.