Skip to content

idlefor/TradeFinanceApp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

7 Commits
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Trade Finance Application

A robust Spring Boot service designed for managing trade finance operations, including real-time currency conversion, transaction auditing, and automated notifications.

πŸš€ Getting Started

Prerequisites

  • Java 21: Required for Record types and modern Spring Boot 3.2+ features.
  • Maven 3.9+: For dependency management and building.

Setup and Installation

  1. Package Alignment: Ensure TradeFinanceApplication.java is located in the com.db.assessment package to avoid component scanning issues.
  2. Compile and Build:
    mvn clean install
  3. Run the Application:
    mvn spring-boot:run
    The server will start on http://localhost:8080 by default.

πŸ›  Monitoring & Health (Actuator)

The application integrates Spring Boot Actuator to provide production-ready health checks. This allows you to verify that the application and its core services are initialized correctly.

Check Service Health

Visit the health endpoint to see the current status of the application.

  • Endpoint: GET /actuator/health
  • Command:
    curl http://localhost:8080/actuator/health
  • Expected Response:
    {
      "status": "UP"
    }

πŸ§ͺ Testing the API

1. Currency Conversion

Perform currency conversions between USD, EUR, SGD, and GBP. This service validates the input amount and checks for supported currency codes.

  • Endpoint: POST /api/v1/trade-finance/convert
  • Test Command:
    curl -X POST http://localhost:8080/api/v1/trade-finance/convert \
         -H "Content-Type: application/json" \
         -d '{"amount": 500, "from": "EUR", "to": "USD"}'

2. Test a Transaction Submission

This is the primary workflow test. It triggers a series of backend actions: Validation β†’ Auto-Approval Logic β†’ Auditing β†’ Notification.

  • Endpoint: POST /api/v1/trade-finance/transaction
  • Test Command:
    curl -X POST http://localhost:8080/api/v1/trade-finance/transaction \
         -H "Content-Type: application/json" \
         -d '{
               "amount": 1250.0,
               "currency": "USD",
               "submittedBy": "user@db.com"
             }'

Verification Steps:

  1. Response Status: Check if you receive a 200 OK (Approved) or 202 Accepted (Pending).
  2. Application Logs: Check the console for an audit entry: AUDIT: TRANSACTION_SUBMITTED | user@db.com | 1250.0 USD STATUS=...
  3. Notification: If approved, look for the log notification: [LOG-NOTIFY] to=user@db.com | Transaction Approved

3. Review Audit Logs

Verify that actions were recorded in the system audit trail.

  • Endpoint: GET /api/v1/trade-finance/audit?limit=5
  • Command:
    curl http://localhost:8080/api/v1/trade-finance/audit?limit=5


πŸ— Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Trade Finance API                        β”‚
β”‚                    (Spring Boot 3.2.4)                      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  Controller    │────────▢│  GlobalExceptionHandler β”‚   β”‚
β”‚  β”‚                β”‚         β”‚  (@ControllerAdvice)    β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚           β”‚                                                 β”‚
β”‚           β”‚ inject                                          β”‚
β”‚           β–Ό                                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚   Services     │────────▢│    AppProperties        β”‚   β”‚
β”‚  β”‚  - Converter   β”‚         β”‚ (@ConfigurationProps)   β”‚   β”‚
β”‚  β”‚  - Audit       β”‚         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚  β”‚  - Notificationβ”‚                                        β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜                                        β”‚
β”‚           β”‚                                                 β”‚
β”‚           β”‚ wired by                                        β”‚
β”‚           β–Ό                                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                        β”‚
β”‚  β”‚   AppConfig    β”‚  ← @Profile, @Conditional, @Bean       β”‚
β”‚  β”‚  (Bean Factory)β”‚                                        β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                        β”‚
β”‚                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key Components

Component Responsibility Pattern
AppProperties Binds application.yml to Java objects @ConfigurationProperties + @Validated
AppConfig Wires beans per environment @Profile, @Conditional, @Bean
GlobalExceptionHandler Centralizes error responses @ControllerAdvice + @ExceptionHandler
TradeFinanceController Exposes REST endpoints @RestController + dependency injection
Service Implementations Business logic Interface segregation + strategy pattern

πŸ“‚ Project Architecture

  • com.db.assessment.controller: REST controllers for API exposure.
  • com.db.assessment.service: Core interfaces (AuditService, CurrencyConverter, NotificationService) and models (AuditEntry).
  • com.db.assessment.service.impl: Business logic implementations including:
    • MockCurrencyConverter (Dev) / LiveCurrencyConverter (Prod)
    • DatabaseAuditService (Active) / NoOpAuditService (Disabled)
    • LogNotificationService (Console) / EmailNotificationService (SMTP)
  • com.db.assessment.exception: Unified error handling returning structured ErrorResponse objects.

βš™οΈ Configuration & Profiles

The application behavior is driven by the active Spring Profile:

  • dev: Uses mock data and console logging.
  • prod: Uses live FX rates and email notification services.

🌐 REST API Endpoints

Base URL

http://localhost:8080/api/v1/trade-finance

Endpoints

Method Path Description
GET /config Returns active configuration
POST /convert Currency conversion
GET /rates Current FX rates (cached)
GET /audit?limit=10 Recent audit log
POST /transaction Submit transaction for approval

Examples

1. Currency Conversion

curl -X POST http://localhost:8080/api/v1/trade-finance/convert \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 1000,
    "from": "USD",
    "to": "EUR"
  }'

Response:

{
  "from": "USD",
  "to": "EUR",
  "original": 1000.0,
  "converted": 1087.0,
  "timestamp": "2026-04-19T14:30:00Z"
}

2. Submit Transaction

curl -X POST http://localhost:8080/api/v1/trade-finance/transaction \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 5000,
    "currency": "USD",
    "submittedBy": "trader1"
  }'

Response (dev β€” auto-approve):

{
  "status": "APPROVED",
  "amount": 5000.0,
  "currency": "USD",
  "submittedBy": "trader1",
  "timestamp": "2026-04-19T14:30:00Z"
}

3. Error Handling

curl -X POST http://localhost:8080/api/v1/trade-finance/convert \
  -H "Content-Type: application/json" \
  -d '{
    "amount": -100,
    "from": "USD",
    "to": "EUR"
  }'

Response (400 Bad Request):

{
  "status": 400,
  "code": "INVALID_INPUT",
  "message": "Amount below minimum: 1.0",
  "timestamp": "2026-04-19T14:30:00Z"
}

πŸ§ͺ Running Tests

Test Pyramid

               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
               β”‚  15 Integration β”‚  @SpringBootTest + MockMvc
               β”‚  (Controller)   β”‚  Full Spring context
               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚  20 Context Tests β”‚  @SpringBootTest
              β”‚  (Bean Wiring)    β”‚  Profile verification
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚    35+ Unit Tests         β”‚  No Spring β€” FAST
          β”‚ (Business Logic)          β”‚  Pure Java
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Run All Tests

mvn test

Run Specific Test Classes

# Unit tests (fast, no Spring)
mvn test -Dtest="TradeFinanceTests\$AppPropertiesUnitTests"
mvn test -Dtest="TradeFinanceTests\$TransactionValidatorTests"

# Integration tests (Spring context)
mvn test -Dtest="TradeFinanceTests\$ControllerTests"
mvn test -Dtest=ExceptionHandlerTests

# Profile-specific
mvn test -Dtest="TradeFinanceTests\$DevProfileContextTests"
mvn test -Dtest="TradeFinanceTests\$TestProfileContextTests"

Test Coverage Summary

Test Class Tests Coverage
AppPropertiesUnitTests 9 Config binding, defaults
TransactionValidatorTests 10 Business rules, edge cases
FxRateCacheTests 7 Cache operations
DevProfileContextTests 6 Bean wiring (dev profile)
TestProfileContextTests 3 Bean wiring (test profile)
ControllerTests 12 REST endpoints
AppConfigBeanTests 9 Bean factory methods
ExceptionHandlerTests 9 Error handling
Total 65+ All layers

πŸ“ Project Structure

src/
β”œβ”€β”€ main/
β”‚   β”œβ”€β”€ java/com/db/assessment/
β”‚   β”‚   β”œβ”€β”€ AssessmentApplication.java           # Main entry point
β”‚   β”‚   β”œβ”€β”€ config/
β”‚   β”‚   β”‚   β”œβ”€β”€ AppProperties.java               # @ConfigurationProperties
β”‚   β”‚   β”‚   └── AppConfig.java                   # Bean factory
β”‚   β”‚   β”œβ”€β”€ controller/
β”‚   β”‚   β”‚   └── TradeFinanceController.java      # REST endpoints
β”‚   β”‚   β”œβ”€β”€ exception/
β”‚   β”‚   β”‚   └── GlobalExceptionHandler.java      # @ControllerAdvice
β”‚   β”‚   └── service/
β”‚   β”‚       β”œβ”€β”€ CurrencyConverter.java           # Interface
β”‚   β”‚       β”œβ”€β”€ AuditService.java                # Interface
β”‚   β”‚       β”œβ”€β”€ NotificationService.java         # Interface
β”‚   β”‚       └── impl/
β”‚   β”‚           └── ServiceImplementations.java  # 6 implementations
β”‚   └── resources/
β”‚       └── application.yml                      # Multi-profile config
└── test/
    └── java/com/db/assessment/
        β”œβ”€β”€ TradeFinanceTests.java               # Main test suite
        └── ExceptionHandlerTests.java           # Error handling tests

πŸ”§ Configuration Profiles

dev (Developer-Friendly)

app:
  trade-finance:
    auto-approve: true         # Auto-approve transactions
    max-transaction-amount: 99999999.00
  audit:
    enabled: true

Run: mvn spring-boot:run

test (Fast, Silent)

app:
  trade-finance:
    max-transaction-amount: 50000.00
  audit:
    enabled: false             # NoOp audit
  rate-limit:
    enabled: false             # No throttling

Run: mvn test

prod (Production-Grade)

app:
  trade-finance:
    auto-approve: false        # Manual approval
    settlement-mode: "T+1"
  security:
    require-https: true
  rate-limit:
    requests-per-second: 50    # Stricter limits

Run: mvn spring-boot:run -Dspring-boot.run.profiles=prod


⚠️ Exception Handling

Supported Exception Types

Exception HTTP Status Error Code Example
IllegalArgumentException 400 INVALID_INPUT "Amount below minimum"
MethodArgumentNotValidException 400 VALIDATION_FAILED @Valid failures
HttpMessageNotReadableException 400 MALFORMED_JSON Invalid JSON
MethodArgumentTypeMismatchException 400 TYPE_MISMATCH ?limit=abc
NoSuchElementException 404 RESOURCE_NOT_FOUND Not found
UnsupportedCurrencyException 400 UNSUPPORTED_CURRENCY Custom exception
InsufficientFundsException 422 INSUFFICIENT_FUNDS Custom exception
Exception (catch-all) 500 INTERNAL_ERROR Unexpected errors

Error Response Format

{
  "status": 400,
  "code": "INVALID_INPUT",
  "message": "Amount below minimum: 1.0",
  "timestamp": "2026-04-19T14:30:00Z",
  "details": {}
}

About

A robust Spring Boot service designed for managing trade finance operations, including real-time currency conversion, transaction auditing, and automated notifications.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages