Simple Retry

The simplest form of retry is just to add the @Retryable annotation to any type or method. The default behaviour of @Retryable is to retry 3 times with an exponential delay of 1 second between each retry. (first attempt with 1s delay, second attempt with 2s delay, third attempt with 3s delay)

For example:

Simple Retry Example

  1. @Retryable
  2. public List<Book> listBooks() {
  3. // ...

Simple Retry Example

  1. @Retryable
  2. List<Book> listBooks() {
  3. // ...

Simple Retry Example

  1. @Retryable
  2. open fun listBooks(): List<Book> {
  3. // ...

With the above example if the listBooks() method throws a RuntimeException it will be retried until the maximum number of attempts is reached.

The multiplier value of the @Retryable annotation can be used to configure a multiplier used to calculate the delay between retries, thus allowing exponential retry support.

Note also that the @Retryable annotation can be applied on interfaces and the behaviour will be inherited through annotation metadata. The implication of this is that @Retryable can be used in combination with Introduction Advice such as the HTTP Client annotation.

To customize retry behaviour you can set the attempts and delay members, For example to configure 5 attempts with a 2 second delay:

Setting Retry Attempts

  1. @Retryable( attempts = "5",
  2. delay = "2s" )
  3. public Book findBook(String title) {
  4. // ...

Setting Retry Attempts

  1. @Retryable( attempts = "5",
  2. delay = "2s" )
  3. Book findBook(String title) {
  4. // ...

Setting Retry Attempts

  1. @Retryable(attempts = "5", delay = "2s")
  2. open fun findBook(title: String): Book {
  3. // ...

Notice how both attempts and delay are defined as strings. This is to support configurability through annotation metadata. For example you can allow the retry policy to be configured using property placeholder resolution:

Setting Retry via Configuration

  1. @Retryable( attempts = "${book.retry.attempts:3}",
  2. delay = "${book.retry.delay:1s}" )
  3. public Book getBook(String title) {
  4. // ...

Setting Retry via Configuration

  1. @Retryable( attempts = "\${book.retry.attempts:3}",
  2. delay = "\${book.retry.delay:1s}")
  3. Book getBook(String title) {
  4. // ...

Setting Retry via Configuration

  1. @Retryable(attempts = "\${book.retry.attempts:3}", delay = "\${book.retry.delay:1s}")
  2. open fun getBook(title: String): Book {
  3. // ...

With the above in place if book.retry.attempts is specified in configuration it will be bound the value of the attempts member of the @Retryable annotation via annotation metadata.