Simple Retry

The simplest form of retry is just to add the @Retryable annotation to a type or method. The default behaviour of @Retryable is to retry three times with an exponential delay of one 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 is 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, allowing exponential retry support.

Note also that the @Retryable annotation can be applied on interfaces, and the behaviour is 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, set the attempts and delay members, For example to configure five attempts with a two 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",
  2. delay = "2s")
  3. open fun findBook(title: String): Book {
  4. // ...

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}",
  2. delay = "\${book.retry.delay:1s}")
  3. open fun getBook(title: String): Book {
  4. // ...

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