openrewrite / openrewrite/rewrite-spring

Spring Boot 4 - Use Retry from Spring Framework 7

Open
#1,000 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

recipe
Dominant language
Java
Stars
403
Forks
149
Avg merge
2h 33m
Merged PRs (30d)
10

Description

What problem are you trying to solve?

I would like to upgrade to Spring Boot 4 since Spring-Retry got replaced with retry functionality in Spring-Core i would love to have a receipt that migrates SB 3.0 Retries to SB 4.0 Retries

What precondition(s) should be checked before applying this recipe?

That the Project is upgraded to SB 4

Describe the situation before applying the recipe

import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.retry.annotation.Recover;
import org.springframework.stereotype.Service;

@Service
class A {

    @Retryable(
        value = SomeCustomException.class,
        maxAttemptsExpression = "${some.config.retry.maxAttempts:2}",
        backoff = @Backoff(
            delayExpression = "${some.config.delay:200}"
        )
    )
    public void foo(String bar) {
        int i = Integer.parseInt(bar);

        if (i != 67) {
            throw new SomeCustomException("I know that a retry does not make sense here");
        }
    }

    @Recover
    public void recoverFoo(SomeCustomException e, String bar) {
        System.out.println("Exception: " + e);
        System.out.println("Failed input: " + bar);
        System.out.println("That was not cringe enough");
    }
}

Describe the situation after applying the recipe

import org.springframework.resilience.annotation.Retryable;
import org.springframework.stereotype.Service;

@Service
class A {

    @Retryable(
        includes = SomeCustomException.class,
        maxAttemptsString = "${some.config.retry.maxAttempts:2}",
        delayString = "${some.config.delay:200}"
    )
    public void foo(String bar) {
        int i = Integer.parseInt(bar);

        if (i != 67) {
            throw new SomeCustomException("I know that a retry does not make sense here");
        }
    }

    public void fooWithRecovery(String bar) {
        try {
            foo(bar);
        } catch (Exception e) {
            recoverFoo(e, bar);
        }
    }

    void recoverFoo(Exception e, String bar) {
        System.out.println("Exception: " + e);
        System.out.println("Failed input: " + bar);
        System.out.println("That was not cringe enough");
    }
}

Have you considered any alternatives or workarounds?

Since we use it a lot i would ask Copilot (with claude i guess) to upgrade the code to Spring Framework 7 Retry

Any additional context

Yeah the problem could be that the Recover call (try catch block) could need to be implemented in calling services

Are you interested in contributing this recipe to OpenRewrite?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start from the Spring Retry annotations and the before/after Java examples in the issue, with the Spring Boot 4 upgrade as the precondition. Determine how the recipe should migrate retry attributes and handle @Recover methods, including recovery calls in calling services. Done means the migration is represented by a working OpenRewrite recipe and its behavior matches the supplied after example.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring, spring-boot
Domain
backend, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.