Capstone: A Real Java Application

Capstone Overview & Requirements

15 min Lesson 1 of 13

Capstone Overview & Requirements

You have made it through OOP, generics, collections, streams, concurrency, I/O, and JDBC. This capstone ties every piece together into a single coherent application. Rather than an isolated exercise, you will build a small but realistic program — one you could confidently show in a code review or a portfolio.

What We Are Building

The project is a Personal Finance Tracker — a command-line application that allows a user to record income and expense transactions, categorise them, generate summary reports, and persist data to a local SQLite database between sessions.

This domain is deliberately simple (everyone understands money in/money out) so you can focus on how the code is structured, not on figuring out a complex business domain. Despite its simplicity, it exercises everything you know:

  • OOP & Design — entities, services, repositories, a thin application layer.
  • Generics & Collections — typed lists, maps for category aggregation, optional returns.
  • Streams & Lambdas — filtering, grouping, sorting, and reducing transaction data.
  • JDBC — reading and writing to SQLite; schema bootstrap on first run.
  • I/O — reading user input from the terminal; exporting a CSV report to disk.
  • Exception Handling — meaningful error messages instead of stack traces on bad input.
  • Testing — unit tests for business logic that do not touch the database.
Why a CLI and not a web app? A web layer (servlets, Spring MVC) adds significant scaffolding that would distract from the Java fundamentals this course targeted. A clean CLI lets you concentrate on domain logic, persistence, and code structure — the skills that transfer directly to any framework.

Functional Requirements

The finished application must satisfy the following requirements. Treat these as a product specification — the kind of document you would receive from a stakeholder.

  1. Record a transaction — the user provides a date (YYYY-MM-DD), an amount (positive decimal), a type (INCOME or EXPENSE), a category string, and an optional description. The application validates every field and rejects invalid input with a clear message.
  2. List transactions — show all recorded transactions in reverse-chronological order, formatted as an aligned table in the terminal.
  3. Filter transactions — filter by date range, by type, or by category. Filters may be combined.
  4. Summary report — display total income, total expenses, net balance, and a per-category breakdown — all computed in-memory with the Streams API.
  5. Delete a transaction — remove a record by its ID after a confirmation prompt.
  6. Export to CSV — write the current filtered view (or all records) to a .csv file chosen by the user.
  7. Persistent storage — all data survives application restarts via JDBC + SQLite.

Non-Functional Requirements

Good software is judged on more than features. The capstone explicitly requires:

  • Testability — business logic must be separable from I/O and the database. You will write JUnit 5 unit tests that run without a database connection.
  • Readability — no method longer than ~30 lines, clear naming, no magic strings or numbers without named constants.
  • Robustness — the app must never crash with an unhandled exception from bad user input or a missing database file.
  • Modern Java (17+) — use records for immutable value objects, sealed interfaces where a discriminated union fits, text blocks if helpful, and switch expressions.
Start with requirements, not code. Professional developers read a spec, ask clarifying questions, and sketch the architecture before opening an IDE. The next two lessons (Architecture and Domain Modelling) do exactly that. Resist the urge to start coding from lesson 1.

Scope Boundaries (What We Are Not Building)

Keeping scope tight is a professional skill. The following are explicitly out of scope so the project stays completable in the tutorial time-box:

  • No graphical UI — terminal only.
  • No multi-user support — single local user, no authentication.
  • No network calls or REST API — everything runs locally.
  • No recurring transactions or budgets — those would be natural extensions after the capstone.
Scope creep kills capstone projects. It is tempting to add a budget-planning screen or a web dashboard. Do not. Finish the defined scope cleanly first. Unfinished ambitious projects are far less impressive than small, polished, well-tested ones.

Technology Choices & Rationale

The project uses nothing outside the Java 17 standard library plus two small, well-known libraries:

  • SQLite via the org.xerial:sqlite-jdbc driver — zero-configuration embedded database; the entire database is a single file. No server to install.
  • JUnit 5 + AssertJ — the de-facto standard for Java unit testing.

Build tool: Maven (covered in the build-tools tutorial). The pom.xml will declare these dependencies so the project builds with a single mvn package.

<!-- pom.xml dependency excerpt --> <dependency> <groupId>org.xerial</groupId> <artifactId>sqlite-jdbc</artifactId> <version>3.45.3.0</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>5.10.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <version>3.25.3</version> <scope>test</scope> </dependency>

High-Level Tutorial Road Map

Here is how the remaining nine lessons build on each other:

  1. Capstone Overview & Requirements (this lesson) — define what we build and why.
  2. Designing the Architecture — layered architecture, package layout, dependency rules.
  3. Modelling the Domain — records, enums, value objects; immutability by default.
  4. Building the Data Layer — JDBC repository pattern, schema bootstrap, connection management.
  5. Implementing Business Logic — service layer, Streams-based aggregation, filtering.
  6. Adding the Application Interface — the CLI command loop, input parsing, output formatting.
  7. Error Handling & Validation — custom exceptions, input validation, graceful degradation.
  8. Testing the Application — unit testing services with in-memory fakes; integration testing the repository.
  9. Packaging & Running — fat JAR with the Maven Shade plugin, running anywhere with java -jar.
  10. Wrap-Up & Next Steps — reflection, extensions you can add, where to go after this course.

Your Action Items Before Lesson 2

To follow along actively rather than passively, do the following before the next lesson:

  1. Create a new Maven project: mvn archetype:generate -DgroupId=com.example.finance -DartifactId=finance-tracker -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
  2. Add the three dependencies above to your pom.xml and confirm mvn compile succeeds.
  3. Write down, in plain English, the five most important things the app must do correctly. Compare your list to the functional requirements above — gaps are design questions to answer in lesson 2.
Reading requirements critically is a professional skill. Any ambiguity you notice now (e.g., "what happens if the user enters a future date?") is a real design decision. In a team you would raise it in a ticket; here, you will make a deliberate choice and document it in a comment. That is the capstone mindset.