Spring Retry, because Winter is coming

OK, this is actually not about the winter, which as we all know has already come. It is about Spring Retry, a small Spring Framework library that allows us to add retry functionality to any task that should be retryable.

There’s a very good tutorial here, explaining how the simple retry and recovery is set up. It explains very well how to add a spring-retry dependency, use @Retryable and @Recover annotation and use RetryTemplate with simple policies. What I’d like to linger on is a slightly more complicated case when we actually want to apply different retry behavior based on the type of the exception. This makes sense because we might know that some exceptions are recoverable and some are not, and therefore it doesn’t make too much sense to try and recover from them. For that, there is a specific retry strategy implementation which is called ExceptionClassifierRetryPolicy, which is used with the Spring RetryTemplate.

Let’s suppose we can only recover from IO Exceptions and skip all others. We will create three classes to extend RetryCallback and one class to extend RecoveryCallback to better show what happens inside:

Then we set up our RetryTemplate. We’ll be using a SimpeRetryPolicy with the fixed number of attempts for the IOException and a NeverRetryPolicy which just allows the initial attempt for everything else.

Now we need to use these callbacks to demonstrate how they work. First the successfull execution, which is very simple:

The output for it is as follows:

*** Executing successfull callback...
Success callback: attempt 0

Then the Exception:

*** Executing Exception callback...
Exception callback: attempt 0
Attempts exhausted. Total: 1
Last exception: Test Exception

And at last our IOException:

*** Executing IO Exception callback...
IO Exception callback: attempt 0
IO Exception callback: attempt 1
IO Exception callback: attempt 2
Attempts exhausted. Total: 3
Last exception: Test IO Exception

As we can see, only IOException initiated three attempts. Note that the attempts are numbered from 0 because when the callback is executed the attempt is not exhausted, so the last attempt has #2 and not #3. But on RecoveryCallback all the attempts are exhausted, so the context holds 3 attempts.

We can also see that the RecoveryCallback isn’t called when the attempts were a success. That is, it is only called when the execution ended with an exception.

The RetryTemplate is synchronous, so all the execution happens in our main thread. That is why I added try/catch blocks around the calls, to allow the program run all three examples without a problem. Otherwise the retry policy would rethrow the exception after its last unsuccessful attempt and would stop the execution.

There is also a very interesting CompositeRetryPolicy which allows to add several policies and delegates to call them in order, one by one. It can also allow to create quite a flexible retry strategy, but that is another topic in itself.

I think that spring-retry is a very useful library which allows to make common retryable tasks more predictable, testable and easier to implement.

 

 

Advertisements

About Maryna Cherniavska

I have productively spent 10+ years in IT industry, designing, developing, building and deploying desktop and web applications, designing database structures and otherwise proving that females have a place among software developers. And this is a good place.
This entry was posted in java, Programming, Uncategorized and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s