Skip to content

Springboot project structure with idempotency logic#1

Open
Tparfaite wants to merge 1 commit into
SheCanCODE-Capstone-Projects:mainfrom
Tparfaite:ft-implement-idempotency-gateway
Open

Springboot project structure with idempotency logic#1
Tparfaite wants to merge 1 commit into
SheCanCODE-Capstone-Projects:mainfrom
Tparfaite:ft-implement-idempotency-gateway

Conversation

@Tparfaite

@Tparfaite Tparfaite commented May 14, 2026

Copy link
Copy Markdown

ABOUT THE PR

  • Initializing the spring boot project structure with idempotency logic

Summary by CodeRabbit

  • New Features

    • Added a payment processing API endpoint that requires an Idempotency-key header to ensure idempotent transaction handling and prevent duplicate processing.
    • Caches payment responses for duplicate valid requests and returns appropriate error codes for missing headers or conflicting request data.
  • Chores

    • Initialized project configuration and build setup.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR introduces a new Spring Boot application providing a REST endpoint at POST /api/process-payment that implements idempotency-key–based duplicate detection. The application uses in-memory caching and per-key locking to serialize concurrent requests and prevent duplicate payment processing.

Changes

Idempotency Payment Processor

Layer / File(s) Summary
Project Configuration and Build Setup
.gitignore, pom.xml, src/main/resources/application.properties
Maven project definition with Spring Boot 3.2.5 and Java 17, including spring-boot-starter-web dependency and build plugin configuration. Server port set to 8080. Project ignores build artifacts, IDE metadata, and system files.
Spring Boot Application Entrypoint
src/main/java/com/igirepay/Application.java
Spring Boot bootstrap class that launches the application via SpringApplication.run().
Payment Idempotency Controller
src/main/java/com/igirepay/controller/PaymentController.java
REST controller implementing POST /api/process-payment with three concurrent hash maps for response caching, request body tracking, and per-key locking. Validates the Idempotency-key header (400 if missing), acquires a per-key ReentrantLock, detects request body conflicts (409 if body differs for an existing key), returns cached responses with X-Cache-Hit: true for duplicates, and stores newly built 201 responses for first-time requests.

Sequence Diagram

flowchart TD
  A["POST /api/process-payment"] --> B["Idempotency-key header present?"]
  B -->|No| C["Return 400 BAD_REQUEST"]
  B -->|Yes| D["Acquire per-key ReentrantLock"]
  D --> E["Lock acquired"]
  E --> F["Key exists in response cache?"]
  F -->|No| G["Store request body<br/>Process payment<br/>Build 201 CREATED response<br/>Cache response"]
  G --> H["Return cached response"]
  F -->|Yes| I["Request body matches<br/>stored body?"]
  I -->|No| J["Return 409 CONFLICT"]
  I -->|Yes| K["Return cached response<br/>Set X-Cache-Hit: true"]
  K --> H
  J --> H
  H --> L["Release lock"]
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A gateway is born with a springy new boot,
Where payments stay idempotent, each key at the root.
Locks guard the cache and conflicts take flight,
No duplicate transactions—just duplicates right! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: setting up a Spring Boot project structure with a payment idempotency gateway controller.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
src/main/java/com/igirepay/controller/PaymentController.java (1)

65-65: 🏗️ Heavy lift

Consider async processing instead of blocking the request thread.

The Thread.sleep(2000) blocks the HTTP request thread for 2 seconds, which limits throughput and can exhaust the server's thread pool under load. For production payment processing, consider using asynchronous processing with @Async or reactive patterns (WebFlux) to avoid blocking.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/igirepay/controller/PaymentController.java` at line 65, The
Thread.sleep(2000) in PaymentController is blocking the HTTP request thread;
remove this call and move the delay/long-running work into an asynchronous
execution path. Replace the blocking sleep with an async delegate (e.g., create
a PaymentProcessingService method and annotate it with `@Async` or return
CompletableFuture/Mono) and have the controller call that async method and
return immediately (DeferredResult/CompletableFuture/Mono) to the client. Ensure
you configure an Executor/@EnableAsync if using `@Async`, or use Reactor types if
migrating to WebFlux, and keep Thread.sleep removed from any controller
request-handling method.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.gitignore:
- Line 3: Replace the incorrect ignore pattern ".ideal" with the correct
IntelliJ directory name ".idea" in the .gitignore entry so IntelliJ project
metadata is properly ignored; update the token ".ideal" to ".idea" wherever it
appears in the .gitignore file.

In `@pom.xml`:
- Around line 24-30: POM is missing test dependencies; update the <dependencies>
section to add standard test artifacts so unit and integration tests for
idempotency and payment flows can run: include
org.springframework.boot:spring-boot-starter-test (for Spring testing, MockMvc,
AssertJ), junit-jupiter (JUnit 5) and org.mockito:mockito-core (or
mockito-junit-jupiter) with test scope, and any additional test helpers you use;
ensure these entries are added alongside the existing
org.springframework.boot:spring-boot-starter-web dependency so test frameworks
are available for classes like your controllers/services handling idempotency.
- Line 16: The project POM currently pins Spring Boot to
<version>3.2.5</version>; update this to <version>3.5.14</version> (or plan
migration to 4.x) by changing the Spring Boot parent/version declaration in the
pom so the build uses 3.5.14; after updating, run mvn -U clean verify and
address any deprecation or dependency compatibility failures (check code
referencing Spring Boot APIs and any plugins that depend on the Spring Boot
version) and update the spring-boot-maven-plugin/configuration if present to
match the new version.

In `@src/main/java/com/igirepay/controller/PaymentController.java`:
- Around line 68-69: In PaymentController locate the handler that reads
requestBody.get("amount") and requestBody.get("currency") and add validation to
ensure both amount and currency are present and non-null (and optionally that
amount is a number and currency is a non-empty string); if validation fails,
return an HTTP 400 response with a clear error message (e.g., "Missing required
field: amount" or "Missing required field: currency") instead of proceeding to
build the "Charged ..." message. Use the existing requestBody, amount, currency
variables and the controller's response mechanism to short-circuit on invalid
input.
- Around line 14-21: The current unbounded ConcurrentHashMap fields
responseCache, requestCache and lockMap in PaymentController will leak memory;
replace them with bounded caches that expire entries (e.g., Caffeine Cache with
a 24h TTL) or wire a Redis-backed cache with TTL; specifically, add the Caffeine
dependency to the project, change the three fields to Cache<String,
ResponseEntity<Map<String,Object>>>, Cache<String, Map<String,Object>>, and
Cache<String, ReentrantLock> respectively (or use a Redis client wrapper),
initialize them with maximum size and expireAfterWrite(24, TimeUnit.HOURS), and
update all usages of responseCache/requestCache/lockMap to use
cache.getIfPresent()/put()/invalidate() (and ensure locks are invalidated when
no longer needed) so entries are automatically evicted and memory is bounded.

---

Nitpick comments:
In `@src/main/java/com/igirepay/controller/PaymentController.java`:
- Line 65: The Thread.sleep(2000) in PaymentController is blocking the HTTP
request thread; remove this call and move the delay/long-running work into an
asynchronous execution path. Replace the blocking sleep with an async delegate
(e.g., create a PaymentProcessingService method and annotate it with `@Async` or
return CompletableFuture/Mono) and have the controller call that async method
and return immediately (DeferredResult/CompletableFuture/Mono) to the client.
Ensure you configure an Executor/@EnableAsync if using `@Async`, or use Reactor
types if migrating to WebFlux, and keep Thread.sleep removed from any controller
request-handling method.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ba87eb5e-cbc3-4276-baf8-4463a10d68a0

📥 Commits

Reviewing files that changed from the base of the PR and between 242a592 and 046e3c3.

📒 Files selected for processing (5)
  • .gitignore
  • pom.xml
  • src/main/java/com/igirepay/Application.java
  • src/main/java/com/igirepay/controller/PaymentController.java
  • src/main/resources/application.properties

Comment thread .gitignore
Comment thread pom.xml
Comment thread pom.xml
Comment thread src/main/java/com/igirepay/controller/PaymentController.java
Comment thread src/main/java/com/igirepay/controller/PaymentController.java
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant