Implementing Idempotent Submissions with Local and Distributed Locks in Java
This article explains the concept of idempotency, common causes of duplicate submissions, and presents several practical solutions—including PRG, token validation, local locks using ConcurrentHashMap, and distributed locks with Redis—accompanied by Spring Boot AOP annotations and full code examples.
Idempotency is a property of an operation that can be performed multiple times without changing the result beyond the initial application. In typical programming scenarios, SELECT queries are naturally idempotent, DELETE operations are idempotent when applied repeatedly, and simple UPDATE statements that set a fixed value are also idempotent, while UPDATE statements that increment a value or INSERT statements are not.
Duplicate submissions often arise from user actions such as clicking a submit button multiple times, refreshing the page, using the browser back button, or from network retries, load balancer resends, and distributed RPC retries.
Several mitigation strategies are discussed:
Post‑Redirect‑Get (PRG) pattern: after a successful form submission, redirect the client to a result page to prevent resubmission on page refresh.
Server‑side token: generate a unique identifier (e.g., stored in the session and sent as a hidden form field) and verify it on each request, discarding repeated submissions.
Database constraints: use unique indexes for INSERT operations and optimistic locking (version field) for UPDATE operations.
Local lock using ConcurrentHashMap and ScheduledThreadPoolExecutor to store a temporary key and release it after a configurable delay.
Distributed lock with Redis: leverage SETNX (or setIfAbsent) to acquire a lock, set an expiration to avoid deadlocks, and release it after processing.
Implementation details for the local lock are provided, including a custom annotation @Resubmit with a delaySeconds attribute, a singleton ResubmitLock class that manages a ConcurrentHashMap, and an AOP aspect ResubmitDataAspect that intercepts methods annotated with @Resubmit, generates a MD5‑based key from request parameters, attempts to acquire the lock, proceeds with the method if successful, or returns a repeat‑submission error otherwise. The aspect also schedules lock release after the configured delay.
Example usage of the annotation on a Spring MVC controller method is shown, followed by Maven dependencies required ( spring-boot-starter-web, spring-boot-starter-aop, spring-boot-starter-data-redis) and Redis configuration properties ( spring.redis.host, spring.redis.port, spring.redis.password).
A Redis‑based lock implementation is also presented. The RedisLockHelper class provides methods to acquire a lock with setIfAbsent, set an expiration, and release the lock either immediately or after a delay using a scheduled executor. The helper handles lock renewal, expiration checks, and safe unlock by verifying the stored UUID.
Finally, the article includes a brief note that the described techniques can be adapted to other signing or token mechanisms, and provides a link to the original blog post for further reference.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Architect Essentials
Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
