Implementing Automatic Idempotency in Spring Boot Using Redis and Interceptors

This article demonstrates how to achieve automatic request idempotency in Spring Boot applications by leveraging Redis for token storage, custom annotations, and interceptor configuration, providing step-by-step code examples for building a Redis service, token service, custom annotation, interceptor, and testing the solution.

Top Architect
Top Architect
Top Architect
Implementing Automatic Idempotency in Spring Boot Using Redis and Interceptors

The article explains the importance of idempotency for public APIs and defines idempotency as the property that multiple identical requests produce the same effect as a single request.

It outlines four common techniques to guarantee idempotency: unique database indexes, token mechanisms, pessimistic/optimistic locks, and a query‑then‑write pattern.

To implement automatic idempotency, the author builds a Redis‑based token store, a custom @AutoIdempotent annotation, a token service, an interceptor that checks the token, and a Spring MVC configuration that registers the interceptor.

Redis service implementation (simplified):

@Component
public class RedisService {
    @Autowired
    private RedisTemplate redisTemplate;
    public boolean set(final String key, Object value) { ... }
    public boolean setEx(final String key, Object value, Long expireTime) { ... }
    public boolean exists(final String key) { return redisTemplate.hasKey(key); }
    public Object get(final String key) { ... }
    public boolean remove(final String key) { ... }
}

Custom annotation definition:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoIdempotent { }

Token service interface and implementation:

public interface TokenService {
    String createToken();
    boolean checkToken(HttpServletRequest request) throws Exception;
}

@Service
public class TokenServiceImpl implements TokenService {
    @Autowired
    private RedisService redisService;
    @Override
    public String createToken() { ... }
    @Override
    public boolean checkToken(HttpServletRequest request) throws Exception { ... }
}

Web MVC configuration to add the interceptor:

@Configuration
public class WebConfiguration extends WebMvcConfigurerAdapter {
    @Resource
    private AutoIdempotentInterceptor autoIdempotentInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(autoIdempotentInterceptor);
        super.addInterceptors(registry);
    }
}

Interceptor that validates the token on methods annotated with @AutoIdempotent:

@Component
public class AutoIdempotentInterceptor implements HandlerInterceptor {
    @Autowired
    private TokenService tokenService;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) return true;
        Method method = ((HandlerMethod) handler).getMethod();
        AutoIdempotent anno = method.getAnnotation(AutoIdempotent.class);
        if (anno != null) {
            try { return tokenService.checkToken(request); }
            catch (Exception ex) { writeReturnJson(response, JSONUtil.toJsonStr(ResultVo.getFailedResult(101, ex.getMessage()))); throw ex; }
        }
        return true;
    }
    private void writeReturnJson(HttpServletResponse response, String json) throws Exception { ... }
}

Example controller showing token generation and an idempotent endpoint:

@RestController
public class BusinessController {
    @Resource
    private TokenService tokenService;
    @Resource
    private TestService testService;
    @PostMapping("/get/token")
    public String getToken() { String token = tokenService.createToken(); ... }
    @AutoIdempotent
    @PostMapping("/test/Idempotence")
    public String testIdempotence() { String result = testService.testIdempotence(); ... }
}

Testing with Postman demonstrates that the first request succeeds while subsequent identical requests are rejected as duplicate operations, confirming the idempotency enforcement.

In conclusion, the article provides a complete, production‑ready solution for automatic request idempotency in Spring Boot using Redis, custom annotations, and interceptors, improving data consistency and reducing unnecessary load on backend services.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaredisSpring BootInterceptorIdempotency
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.