This post is part of a series delving into the details of the JSR-352 (Java Batch) specification. Each post examines a very specific part of the specification and looks at how it works and how you might use it in a real batch application.To start at the beginning, follow the link to the first post.This series is also available as a podcast on iTunes, Google Play, Stitcher, or use the link to the RSS feed.
The next post in the series is here
A search suggested “Try Again” by Aaliyah or maybe “Coming Around Again” by Carly Simon, but I decided to go with “Round and Round” by Ratt. Trying again is a common theme in music so I’m sure there are a lot of others.
Last time we talked about using Skip processing to skip over a problem without failing the whole job. This time we’re going to look at handling errors via retry processing. Basic retry processing is, as you would expect, just having another try at doing something that didn’t work the first time, but you think might work if you have another go.
The processing is pretty easy. Let’s consider a retryable error from an
ItemReader (processing is similar for retryable errors from the processor or writer). Your reader tries to read a record to be processed and fails. It isn’t something wrong with the record and it isn’t something you consider fatal. Fatal might be something like the file you were reading from is suddenly gone. A retryable error might be something like a temporary connection failure to a remote database. The database might be down, but it also might just be a glitch in the network. We should try again at least a time or two.
In this case the application code in the reader throws a specific exception you’ve defined for this situation. Syntax in the JSL indicates this exception is a retryable error.
Side Note: There are both retry and retry-rollback exceptions and the syntax in JSL gets a bit wonky. We’ll look at that later. For now we are just looking at how retry processing works, not how you ask for it to happen.
What happens now? First of all, the
RetryReadListener (if you have one) will get control in its
onRetryReadException method and get passed the exception your reader threw. I’m not sure what you would do here. Maybe there is some check you to do to see if the remote resource is still there, or at least log a warning about the failure and that you are trying again.
And then the reader just gets called again to try again to read the next item. There is a maximum number of times you can retry reading records (and a maximum skip limit). Both are specified in the chunk element and default to unlimited.
What if you have both skippable exceptions and retryable exceptions thrown from the reader? When the reader gets control how does it know if it is supposed to retry reading the same record or just read the next one? You have to have some flags or counters or something local to the reader (although maybe accessible to the Listeners) to help the reader figure out what it is supposed to do. It threw the exception, so it knows what happened and needs to adjust so it does the right thing when it is called again.