Raw Java. Real concurrency. AI fraud checks. No heavy frameworks.
Banking System is a self-contained, demo-grade banking backend built entirely on raw Java 17 — no Spring Boot, no Hibernate, no application server. It pairs a hand-crafted HttpServer REST API with a React + Vite frontend and an AI-assisted fraud detection pipeline that gracefully degrades to deterministic heuristics when no API key is configured.
It's designed to be easy to run, easy to read, and genuinely interesting to demonstrate.
Most banking demos use Spring Boot and hide everything behind annotations. This project exposes the raw mechanics:
com.sun.net.httpserver.HttpServer— manual route registration, manual request parsing, manual response writing- Manual JSON handling via
org.json— no ObjectMapper magic, every field read and validated explicitly - Zero reflection, zero dependency injection — you can trace every call from HTTP request to in-memory state update
This is the difference between using a framework and understanding what it does.
The fraud detection system is production-inspired in its design:
- When
GROQ_API_KEYis set → sends transaction context to an LLM for intelligent fraud scoring - When the API is unavailable or unconfigured → falls back automatically to a deterministic heuristic engine (amount thresholds, velocity checks, account age)
- APIs always respond — the fraud check never blocks or crashes a transaction
- This is exactly how real fraud systems work: AI augments, heuristics guarantee
Deposits, withdrawals, and transfers are processed with:
- Per-account
ReentrantLock— prevents race conditions on concurrent balance updates - Atomic in-memory state using
ConcurrentHashMap— no lost updates - Rollback logic on transfer failure — if credit fails after debit, the debit is reversed
No database, no JPA — just Java concurrency primitives used correctly.
- Single JSON jar (
lib/json-20231013.jar) — the only external dependency run.bat/start-all.bat— one command to start backend + frontend togetherscripts/api-test.ps1— PowerShell smoke test suite to demo all endpoints immediately- Built frontend in
frontend/dist— no npm install needed to see the UI
- API key read from environment variable
GROQ_API_KEYorconfig/local.properties config/local.properties.exampleprovided — fill and rename, never commit.gitignorepre-configured to exclude all local secrets
┌─────────────────────────────────────────────────────────────┐
│ React Frontend (Vite) │
│ frontend/src · frontend/dist │
│ Accounts UI · Transaction Forms · Dashboard │
└──────────────────────────┬──────────────────────────────────┘
│ HTTP :8080
┌──────────────────────────▼──────────────────────────────────┐
│ Java HttpServer (Raw, No Framework) │
│ Manual Route Dispatch │
└───┬──────────────────────┬──────────────────────┬───────────┘
│ │ │
┌───▼──────────┐ ┌────────▼───────┐ ┌───────────▼─────────┐
│ Account │ │ Transaction │ │ Fraud Detection │
│ Handler │ │ Handler │ │ Handler │
│ │ │ │ │ │
│ create/list │ │ deposit │ │ AI call (Groq) │
│ get/update │ │ withdraw │ │ ↓ on failure │
│ │ │ transfer │ │ Heuristic fallback │
└───┬──────────┘ └────────┬───────┘ └───────────┬─────────┘
│ │ │
└──────────────────────┼───────────────────────┘
│
┌──────────────────────────▼──────────────────────────────────┐
│ In-Memory Data Store │
│ ConcurrentHashMap<AccountId, Account> │
│ ConcurrentHashMap<AccountId, ReentrantLock> │
│ List<Transaction> (synchronized) │
└─────────────────────────────────────────────────────────────┘
banking_system-main/
├── pom.xml ← Maven build config
├── run.bat ← Start backend only
├── start-all.bat ← Start backend + frontend together
├── lib/
│ └── json-20231013.jar ← Only external dependency
├── config/
│ └── local.properties.example ← Copy → local.properties, add API key
├── scripts/
│ └── api-test.ps1 ← PowerShell smoke tests for all endpoints
├── src/main/java/com/banking/
│ ├── Main.java ← Entry point, server bootstrap
│ ├── handlers/
│ │ ├── AccountHandler.java ← CRUD for accounts
│ │ ├── TransactionHandler.java ← Deposit / withdraw / transfer
│ │ └── FraudHandler.java ← Fraud check endpoint
│ ├── services/
│ │ ├── AccountService.java ← Account business logic + locking
│ │ ├── TransactionService.java ← Atomic transaction processing
│ │ └── FraudDetectionService.java ← AI call + heuristic fallback
│ ├── models/
│ │ ├── Account.java
│ │ └── Transaction.java
│ ├── tools/
│ │ └── TestRunner.java ← Internal demo test harness
│ └── utils/
│ └── ApiConfig.java ← Reads GROQ_API_KEY from env/config
└── frontend/
├── src/ ← React + Vite source
└── dist/ ← Pre-built assets (serve immediately)
- Java 17+
- Maven 3.8+ (or use the
javac/javascripts directly) - Node.js 18+ (only if rebuilding the frontend)
start-all.batStarts the Java backend on :8080 and serves the React frontend. Open http://localhost:5173 for the UI.
run.batAPI available at http://localhost:8080
mvn clean package
java -jar target/banking-system.jarcd frontend
npm install
npm run dev# Set your Groq API key (free at console.groq.com)
export GROQ_API_KEY=your_key_here # Linux / macOS
$env:GROQ_API_KEY="your_key_here" # Windows PowerShellOr create config/local.properties from the example file:
GROQ_API_KEY=your_key_hereIf no key is set, the system automatically falls back to heuristic fraud detection. All endpoints still work.
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/accounts |
Create a new account |
GET |
/api/accounts |
List all accounts |
GET |
/api/accounts/{id} |
Get account by ID |
PUT |
/api/accounts/{id} |
Update account details |
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/transactions/deposit |
Deposit funds |
POST |
/api/transactions/withdraw |
Withdraw funds |
POST |
/api/transactions/transfer |
Transfer between accounts |
GET |
/api/transactions/{accountId} |
Get transaction history |
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/fraud/check |
Run fraud analysis on a transaction |
curl -X POST http://localhost:8080/api/accounts \
-H "Content-Type: application/json" \
-d '{
"name": "Devanshu Sharma",
"email": "devanshu@example.com",
"initialBalance": 5000.00
}'Response:
{
"accountId": "ACC-2024-001",
"name": "Devanshu Sharma",
"email": "devanshu@example.com",
"balance": 5000.00,
"status": "ACTIVE",
"createdAt": "2024-12-01T10:30:00Z"
}curl -X POST http://localhost:8080/api/transactions/transfer \
-H "Content-Type: application/json" \
-d '{
"fromAccountId": "ACC-2024-001",
"toAccountId": "ACC-2024-002",
"amount": 1500.00,
"description": "Rent payment"
}'Response:
{
"transactionId": "TXN-8842",
"status": "COMPLETED",
"amount": 1500.00,
"fraudCheck": {
"score": 12,
"verdict": "SAFE",
"method": "AI",
"reasoning": "Routine transfer within normal velocity range."
}
}curl -X POST http://localhost:8080/api/fraud/check \
-H "Content-Type: application/json" \
-d '{
"accountId": "ACC-2024-001",
"amount": 49999.00,
"type": "WITHDRAWAL"
}'Response:
{
"score": 87,
"verdict": "SUSPICIOUS",
"method": "HEURISTIC",
"flags": ["amount_exceeds_threshold", "unusual_velocity"],
"recommendation": "HOLD_FOR_REVIEW"
}cd scripts
.\api-test.ps1Runs a full create → deposit → transfer → fraud-check sequence and prints pass/fail for each step.
# After starting the server:
mvn exec:java -Dexec.mainClass="com.banking.tools.TestRunner"Transaction Received
│
▼
┌─────────────────────────────────┐
│ Is GROQ_API_KEY configured? │
└──────────┬──────────────────────┘
│ Yes No
▼ ▼
┌─────────────────┐ ┌──────────────────────────┐
│ Groq LLM API │ │ Heuristic Engine │
│ │ │ • Amount threshold │
│ Transaction + │ │ • Velocity check │
│ account context│ │ • Account age check │
│ → fraud score │ │ • Round number flag │
└────────┬────────┘ └─────────────┬────────────┘
│ Failure/timeout │
└───────────────┬───────────┘
│
▼
Fraud Score (0–100)
Verdict: SAFE / SUSPICIOUS / BLOCKED
Always returned — never null
| Layer | Technology |
|---|---|
| Language | Java 17 |
| HTTP Server | com.sun.net.httpserver (zero framework) |
| JSON | org.json (single jar) |
| Concurrency | ConcurrentHashMap + ReentrantLock |
| AI Fraud | Groq API via Java HttpClient |
| Frontend | React + Vite |
| Styling | Tailwind utility classes + custom CSS |
| Build | Maven + javac/java scripts |
| Testing | Internal TestRunner + PowerShell smoke tests |
| Feature | Typical Banking Demo | This Project |
|---|---|---|
| Backend framework | Spring Boot | Raw HttpServer |
| Fraud detection | None / mock | AI + heuristic fallback |
| Concurrency | Framework-managed | Per-account ReentrantLock |
| Transfer atomicity | Not handled | Debit + credit + rollback |
| External dependencies | 20+ jars | One JSON jar |
| Run complexity | mvn spring-boot:run magic |
You see exactly what starts |
| Secrets management | application.properties |
Env var + .gitignore |
| Frontend | None or template | React + Vite, pre-built |
- Add JUnit 5 tests wired into
mvn test - Introduce H2/SQLite for persistence demos
- Add JWT authentication layer
- GitHub Actions CI — build + smoke test on push
- Upgrade Vite/esbuild to clear npm audit warnings
MIT License — see LICENSE for details.