A desktop personal-finance tracker built in Java for the CSE 2006 — Programming in Java course (VITyarthi Build Your Own Project).
The app lets a student track every rupee that goes in and out, set monthly caps per category, see live "are you on track?" alerts and export the data as CSV — all from a clean Swing desktop UI backed by a local SQLite database.
- Local user accounts — register & sign in with a salted SHA-256 password hash (no plaintext, ever).
- Categorised transaction log — add, view and delete income or expense records, each tagged with a category (Food, Rent, Salary…).
- Monthly budgets per category — set a rupee limit for any expense category; the dashboard surfaces an alert as soon as you cross 80 % or 100 % of the cap.
- Reports & analytics — month picker, monthly summary cards (income / expense / net savings), category-level breakdown with percentages.
- CSV export — one click pushes every transaction for the signed-in user into a portable spreadsheet.
- Custom categories — add or delete your own income / expense categories through the UI; the system refuses to delete a category that is still in use.
| Concern | Choice |
|---|---|
| Language | Java 17 (no external language features) |
| UI toolkit | Swing (part of the JDK) |
| Build & deps | Plain javac + java — no Maven/Gradle |
| Database | SQLite via the sqlite-jdbc 3.42 driver |
| Persisted entities | users, categories, transactions, budgets |
| Version control | Git |
The project is intentionally light on tooling — the reviewer can clone,
./run.sh, and watch the GUI open in seconds.
SmartExpenseTracker/
├── README.md ← this file
├── statement.md ← problem statement & scope
├── run.sh / run.bat ← one-click build & launch
├── build.sh ← compile-only helper
├── lib/
│ └── sqlite-jdbc.jar ← bundled SQLite JDBC driver
├── src/com/expensetracker/
│ ├── Main.java ← entry point (sets up DB + EDT)
│ ├── model/ ← POJOs + TransactionType enum
│ │ ├── User.java
│ │ ├── Category.java
│ │ ├── Transaction.java
│ │ ├── Budget.java
│ │ └── TransactionType.java
│ ├── dao/ ← JDBC layer (one class per table)
│ │ ├── DatabaseManager.java
│ │ ├── UserDAO.java
│ │ ├── CategoryDAO.java
│ │ ├── TransactionDAO.java
│ │ └── BudgetDAO.java
│ ├── service/ ← business rules & validation
│ │ ├── AuthService.java
│ │ ├── ExpenseService.java
│ │ ├── BudgetService.java
│ │ └── ReportService.java
│ ├── ui/ ← Swing screens
│ │ ├── Theme.java
│ │ ├── UiUtil.java
│ │ ├── LoginFrame.java
│ │ ├── DashboardFrame.java (5 tabs: Overview, Transactions, Budgets, Reports, Categories)
│ │ └── AddTransactionDialog.java
│ └── util/ ← cross-cutting helpers
│ ├── PasswordHasher.java
│ ├── CSVExporter.java
│ ├── DateUtil.java
│ └── AppException.java
├── docs/
│ ├── diagrams/ ← PlantUML sources + PNG renders
│ └── Project_Report.pdf ← final report for submission
├── screenshots/ ← rendered UI screenshots
└── db/ ← runtime DB lives here (auto-created, gitignored)
24 hand-written Java classes — well over the 5–10 module floor.
- Java 17 or newer on
PATH(any JDK distribution works — Temurin, OpenJDK, Oracle). Verify withjava -version. - No other dependencies. The SQLite driver (
lib/sqlite-jdbc.jar) is bundled with the project.
chmod +x run.sh
./run.sh # macOS / Linux
run.bat # WindowsThe script will compile every .java under src/ into build/classes,
drop a shiny SQL database next to the JAR on first run, and pop the
login window.
./build.shjavac -encoding UTF-8 -d build/classes -cp "lib/sqlite-jdbc.jar" $(find src -name "*.java")
java -cp "build/classes:lib/sqlite-jdbc.jar" com.expensetracker.MainA headless SmokeTest (in tests/) exercises the database, DAOs and
services:
javac -encoding UTF-8 -d build/classes -cp "build/classes:lib/sqlite-jdbc.jar" tests/SmokeTest.java
rm -f db/expense_tracker.db
java -cp "build/classes:lib/sqlite-jdbc.jar" SmokeTestExpected: a green "✅ All smoke tests passed." after 11 steps covering schema, registration, password hashing, transactions, budgets, aggregation, CSV export and constraint enforcement.
- Run
./run.sh. - In the login window, click "Create a new account →".
- Fill in a username (≥ 3 chars), password (≥ 4 chars), any name and email, hit Create account.
- You land on the Overview tab with three empty stat cards.
- Switch to Transactions → click + Add transaction, choose
Income,Salary, an amount, and save. Repeat with a few expenses. - Switch to Budgets → pick a category, set a monthly limit, save. You should now see a banner on Overview when the limit gets close to / exceeds the cap.
- Try Reports and pick a different month to see past summaries.
- Click Export CSV in the header — pick a path — open the file in Excel / Sheets.
A reference sequence using the bundled UITest driver (in tests/)
also exists:
javac -encoding UTF-8 -d build/classes -cp "build/classes:lib/sqlite-jdbc.jar" tests/UITest.java
java -cp "build/classes:lib/sqlite-jdbc.jar" UITestThis renders 8 PNG screenshots into screenshots/.
| # | Screen | File |
|---|---|---|
| 1 | Login / register | screenshots/01_login.png |
| 2 | Empty dashboard | screenshots/02_dashboard_empty.png |
| 3 | Dashboard — Overview | screenshots/03_dashboard_overview.png |
| 4 | Transactions tab | screenshots/04_transactions_tab.png |
| 5 | Budgets tab | screenshots/05_budgets_tab.png |
| 6 | Reports tab | screenshots/06_reports_tab.png |
| 7 | Categories tab | screenshots/07_categories_tab.png |
| 8 | Add transaction | screenshots/08_add_transaction_dialog.png |
The app uses a layered architecture:
┌──────────────────────┐
│ ui (Swing) │ LoginFrame, DashboardFrame, …
└──────────┬───────────┘
│ calls
┌──────────▼───────────┐
│ service (business) │ AuthService, ExpenseService, …
└──────────┬───────────┘
│ uses
┌──────────▼───────────┐
│ dao (JDBC) │ UserDAO, TransactionDAO, …
└──────────┬───────────┘
│ talks to
┌──────────▼───────────┐
│ SQLite (db/*.db) │
└──────────────────────┘
- UI never touches JDBC — it goes through services.
- Services never see raw SQL — they call DAOs.
- Errors cross the layers as a custom
AppException, so the UI shows a friendly message rather than a stack trace.
Full UML, ER and workflow diagrams live in docs/diagrams/ and are
embedded in the project report at docs/Project_Report.pdf.
- Passwords are never stored in plaintext. They are hashed with
SHA-256 over (random 16-byte salt + password) and stored as
salt$digestbase-64 encoded. - All SQL uses
PreparedStatementwith parameter binding — no string concatenation, so SQL injection is not possible. - Every table that holds user data is scoped by
user_id; queries always filter by the signed-in user.
src/— Java source fileslib/sqlite-jdbc.jar— third-party JDBC driver (Apache 2.0)docs/— diagrams and the final report PDFscreenshots/— UI screenshots used in the reportrun.sh/run.bat— build & launch scripts.gitignore— keepsbuild/,db/*.db, IDE files out
Submitted for: VITyarthi Build Your Own Project, course CSE 2006 — Programming in Java.