Implementing Idempotent API with Custom @RepeatSubmit Annotation in Spring

This article explains how to achieve API idempotency in high‑concurrency scenarios by creating a custom @RepeatSubmit annotation, using AOP interception, Redis setNx for locking, and a request‑wrapper to allow repeated reading of request parameters in Spring applications.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Implementing Idempotent API with Custom @RepeatSubmit Annotation in Spring

Idempotency ensures that multiple identical API calls produce the same result as a single call, preventing inconsistent states especially when users repeatedly click a button due to network latency. The article focuses on guaranteeing idempotency for low‑traffic endpoints (e.g., adding a patient) within a configurable time window, typically five seconds.

The solution introduces a custom annotation @RepeatSubmit that can be placed on create, update, or delete endpoints. When the annotation is present, an AOP aspect intercepts the request, extracts the URL, client IP, and request parameters, and builds a unique key.

The key is stored in Redis using the SETNX command with an expiration time. If the key is successfully set, the request proceeds; otherwise, an exception is thrown and handled by a global exception handler, returning a clear error message to the client.

AOP intercepts methods annotated with @RepeatSubmit.

Request URL, IP address, and parameters are collected.

The collected data is transformed into a unique Redis key.

Redis SETNX stores the key with a TTL (default 5 seconds).

If storage succeeds, the request is allowed; if it fails, an exception is raised.

A global exception handler returns a friendly response.

Reading request parameters poses a challenge because @RequestBody streams can be consumed only once. To solve this, the article wraps HttpServletRequest in a custom RepeatedlyRequestWrapper that caches the request body in a byte array, allowing multiple reads via overridden getReader and getInputStream methods.

A filter detects JSON requests, replaces the original HttpServletRequest with the wrapper, and passes the modified request down the filter chain, enabling the AOP aspect to access the body safely.

The final annotation implementation consists of defining com.code.ape.codeape.common.security.annotation.RepeatSubmit and an aspect class

com.code.ape.codeape.common.security.component.CodeapeRepeatSubmitAspect

. The aspect contains the logic described above and checks whether the incoming request has been wrapped, ensuring correct handling of both form‑data and JSON payloads.

In summary, by adding @RepeatSubmit to non‑query endpoints, developers can prevent duplicate submissions within a short time window without altering business logic, leveraging AOP, Redis locking, and a request‑wrapper for reliable parameter access.

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.

BackendJavaaopspringIdempotencyannotation
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

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.