Skip to content

refactor: incremental payment flow refactoring — tests, exceptions, REST API, and async events#179

Open
devin-ai-integration[bot] wants to merge 5 commits intoDevOpsfrom
devin/1777458194-refactor-payment-flows
Open

refactor: incremental payment flow refactoring — tests, exceptions, REST API, and async events#179
devin-ai-integration[bot] wants to merge 5 commits intoDevOpsfrom
devin/1777458194-refactor-payment-flows

Conversation

@devin-ai-integration
Copy link
Copy Markdown

Summary

Incremental 5-phase refactoring of the banking application's payment flows, each committed separately:

Phase 0 — Setup (chore: add H2 test dependency...)

  • Added H2 in-memory database for tests, fixed maven-compiler-plugin from Java 1.8 → 17, created application-test.properties

Phase 1 — Test Generation (feat: add comprehensive test suite for payment flows)

  • AccountServiceTest — 13 unit tests with mocked repositories covering deposit, withdraw, transfer, edge cases
  • BankControllerIntegrationTest — 10 integration tests with MockMvc for all Thymeleaf endpoints
  • AccountServiceTransactionSafetyTest — demonstrates the atomicity problem in transferAmount

Phase 2 — Safer Abstractions (refactor: add custom exceptions, @Transactional, and input validation)

  • Custom exception hierarchy: BankAppExceptionInsufficientFundsException, AccountNotFoundException, DuplicateUsernameException, InvalidAmountException
  • @Transactional on all mutation methods in AccountService
  • Input validation (positive amount check) on deposit/withdraw/transfer
  • Updated controller to catch BankAppException, added catch on deposit endpoint
  • Updated tests to assert custom exception types + new validation tests

Phase 3 — API Standardization (feat: add REST API layer with DTOs...)

  • DTOs: ApiResponse<T>, DepositRequest, WithdrawRequest, TransferRequest, AccountResponse, TransactionResponse
  • BankApiController — REST endpoints at /api/v1/ with constructor injection and HTTP Basic auth
  • GlobalExceptionHandler@RestControllerAdvice mapping exceptions to proper HTTP status codes
  • Split SecurityConfig into two filter chains: API (HTTP Basic, Order 1) and Web (form login, Order 2)
  • 10 API tests covering all endpoints, error responses, and unauthenticated access

Phase 4 — Async Flow Migration (refactor: migrate transaction logging to async event-driven pattern)

  • @EnableAsync on application class
  • TransactionEvent event class and TransactionEventListener with @Async @TransactionalEventListener(AFTER_COMMIT)
  • Refactored AccountService to publish events via ApplicationEventPublisher instead of direct transactionRepository.save()
  • Balance updates remain synchronous/transactional; only transaction audit logging is async
  • Async tests using Awaitility to verify event-driven transaction creation

All 39 tests pass. The existing Thymeleaf UI is fully preserved.

Review & Testing Checklist for Human

  • Verify all 5 commits are present and logically separated (git log)
  • Test the Thymeleaf UI still works: register → login → deposit → withdraw → transfer → view transactions
  • Test REST API endpoints with curl using HTTP Basic auth (POST /api/v1/deposit, POST /api/v1/withdraw, POST /api/v1/transfer, GET /api/v1/balance, GET /api/v1/transactions)
  • Verify error responses return correct HTTP status codes (400 for invalid amount, 404 for account not found, etc.)
  • Confirm async transaction logging: after deposit/withdraw/transfer, verify transaction records appear in GET /api/v1/transactions

Notes

  • Awaitility dependency added for async test assertions
  • H2 is test-scoped only; production still uses MySQL
  • Existing @Autowired field injection in original classes was left as-is to minimize risk
  • The GlobalExceptionHandler catches exceptions from both the REST API and Thymeleaf controllers, but the Thymeleaf controller has its own try/catch blocks that take priority

Link to Devin session: https://app.devin.ai/sessions/455a73a8adb3489697994c00261c6312
Requested by: @joao-cognition

devin-ai-integration Bot and others added 5 commits April 29, 2026 10:23
… add test properties

Co-Authored-By: Joao Esteves <joao.esteves@cognition.ai>
Co-Authored-By: Joao Esteves <joao.esteves@cognition.ai>
Co-Authored-By: Joao Esteves <joao.esteves@cognition.ai>
Co-Authored-By: Joao Esteves <joao.esteves@cognition.ai>
Co-Authored-By: Joao Esteves <joao.esteves@cognition.ai>
@devin-ai-integration
Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@staging-devin-ai-integration
Copy link
Copy Markdown

Devin Review

Status Commit
⚪ Not started

Open in Devin Review (Staging)

💡 Connect your GitHub account to enable automatic code reviews.

@devin-ai-integration
Copy link
Copy Markdown
Author

Test Results — Full Feature Testing

Ran the app locally with H2 in-memory DB. Tested Thymeleaf UI end-to-end and REST API via curl.

Session: https://app.devin.ai/sessions/455a73a8adb3489697994c00261c6312


Unit/Integration Tests

mvn clean test39/39 passed, BUILD SUCCESS


Thymeleaf UI Flow
Step Expected Result
Register "alice" Redirect to /login PASSED
Login as "alice" Dashboard, balance $0.00 PASSED
Deposit $1000 Balance → $1000.00 PASSED
Withdraw $300 Balance → $700.00 PASSED
Register "bob", transfer $200 alice→bob Alice balance → $500.00 PASSED
View Transactions Deposit, Withdrawal, Transfer Out entries PASSED

After Transfer
Transaction History

REST API Endpoints
Endpoint Action Result
POST /api/v1/deposit Deposit $100 → balance 600 PASSED
POST /api/v1/withdraw Withdraw $50 → balance 550 PASSED
POST /api/v1/transfer Transfer $100 to bob → balance 450 PASSED
GET /api/v1/balance Returns balance 450 PASSED
GET /api/v1/transactions Returns 7 transaction records PASSED
Error Handling
Scenario Expected Actual Result
Withdraw $99999 400 HTTP 400, "Insufficient funds" PASSED
Deposit -$50 400 HTTP 400, "Amount must be positive" PASSED
Transfer to "nonexistent" 404 HTTP 404, "Recipient account not found" PASSED
Unauthenticated access 401/302 HTTP 302 (redirect) PASSED

Async transaction logging confirmed working — transactions appear in both UI and API after balance operations complete.

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.

0 participants