A desktop task management application built with JavaFX, SQLite, and Maven following an MVC architecture pattern.
- Overview
- Prerequisites
- Getting Started
- Project Structure
- Architecture
- Layer Responsibilities
- Database Schema
- Key Dependencies
- Building and Running
- Adding a New Feature
- Known Issues
- Roadmap
Task Tracker is a single-user desktop application for managing personal tasks. Users can create, edit, delete, and filter tasks by status. Tasks are automatically derived as Pending, Complete, or Overdue based on their due date and completion state. All data is persisted locally in a SQLite database.
Tech stack:
| Technology | Version | Purpose |
|---|---|---|
| Java | 21 | Runtime and language |
| JavaFX | 21.0.4 | Desktop UI framework |
| SQLite (Xerial JDBC) | 3.45.3.0 | Local data persistence |
| Maven | 3.8+ | Build and dependency management |
| CSS | — | UI styling via JavaFX CSS |
Before running or developing the project, ensure you have the following installed:
- Java 21+
- Maven 3.8+
- IntelliJ IDEA (recommended) — Community or Ultimate edition
JavaFX and SQLite are pulled in automatically by Maven. No additional installation is required for either.
git clone https://github.com/jennabeachcodes/TaskTracker.git
cd TaskTrackermvn clean javafx:runThe application will launch and automatically create a tasks.db SQLite database file in the working directory on first run.
- Open IntelliJ and select File → Open and choose the project root.
- Wait for Maven to resolve dependencies.
- Open
src/main/java/com/tasktracker/Main.java. - Click the green Run button or press
Shift+F10.
TaskTracker/
├── src/
│ └── main/
│ ├── java/
│ │ └── com/tasktracker/
│ │ ├── Main.java # Application entry point
│ │ ├── controller/
│ │ │ └── TaskController.java # Handles UI actions
│ │ ├── dao/
│ │ │ ├── TaskDAO.java # DAO interface
│ │ │ └── TaskDAOImpl.java # SQLite implementation
│ │ ├── model/
│ │ │ └── Task.java # Task entity
│ │ ├── service/
│ │ │ └── TaskService.java # Business logic
│ │ └── view/
│ │ └── TaskView.java # JavaFX UI
│ └── resources/
│ └── style.css # Application stylesheet
├── pom.xml # Maven build configuration
├── tasks.db # SQLite database (auto-created)
└── README.md
The application follows a five-layer MVC architecture. Each layer has a single responsibility and only communicates with the layer directly below it.
┌─────────────────────────────────┐
│ TaskView.java │ ← Presentation layer (JavaFX UI)
└────────────────┬────────────────┘
│ delegates to
┌────────────────▼────────────────┐
│ TaskController.java │ ← Controller layer
└────────────────┬────────────────┘
│ delegates to
┌────────────────▼────────────────┐
│ TaskService.java │ ← Service layer (business logic)
└────────────────┬────────────────┘
│ persists via
┌────────────────▼────────────────┐
│ TaskDAO (interface) │ ← Data access layer
│ TaskDAOImpl (SQLite/JDBC) │
└────────────────┬────────────────┘
│ reads/writes
┌────────────────▼────────────────┐
│ tasks.db │ ← SQLite database
└─────────────────────────────────┘
Task.java (model) is passed between all layers
| Layer | Class | Responsibility |
|---|---|---|
| Presentation | TaskView |
Builds the JavaFX scene graph, binds data to the ObservableList, fires controller methods on user actions. All UI logic lives here. |
| Controller | TaskController |
Receives calls from the view, delegates to the service, then calls view.setTasks() to refresh the UI. No business logic. |
| Service | TaskService |
Validates input, enforces business rules (e.g. title cannot be blank), delegates persistence to the DAO. No SQL, no UI. |
| Data Access | TaskDAO / TaskDAOImpl |
All SQL statements live here. The service depends on the TaskDAO interface, not the implementation, allowing the database to be swapped without touching other layers. |
| Model | Task |
Plain data object passed between all layers. Derives getStatus() at runtime from isComplete and dueDate vs today's date. |
The database is created automatically on first launch. The schema is as follows:
CREATE TABLE IF NOT EXISTS tasks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
description TEXT,
dueDate TEXT, -- stored as ISO-8601 string: YYYY-MM-DD
isComplete INTEGER DEFAULT 0 -- 0 = false, 1 = true
);Note: Task status (Pending / Complete / Overdue) is not stored in the database. It is derived at runtime in
Task.getStatus()by comparingdueDateagainstLocalDate.now().
All dependencies are declared in pom.xml and resolved automatically by Maven.
<!-- JavaFX UI framework -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>21.0.4</version>
</dependency>
<!-- JavaFX FXML support -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>21.0.4</version>
</dependency>
<!-- SQLite JDBC driver (Xerial) -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.45.3.0</version>
</dependency>| Command | Description |
|---|---|
mvn clean javafx:run |
Run the application in development mode |
mvn clean package |
Build a fat JAR to target/TaskTracker-1.0-SNAPSHOT.jar |
java -jar target/TaskTracker-1.0-SNAPSHOT.jar |
Run the built JAR directly |
The maven-shade-plugin is configured in pom.xml to bundle all dependencies into a single executable JAR. Run:
mvn clean package
java -jar target/TaskTracker-1.0-SNAPSHOT.jarJavaFX note: JavaFX native libraries cannot be fully shaded into the JAR. The target machine must have JavaFX installed, or the module path must be provided explicitly:
java --module-path /path/to/javafx-sdk/lib \ --add-modules javafx.controls,javafx.fxml \ -jar target/TaskTracker-1.0-SNAPSHOT.jar
Follow this checklist when extending the application to keep the layer boundaries intact:
Task.java— Add the new field, getter, setter, and update the constructor if needed.TaskDAOImpl.java— Update theCREATE TABLESQL and all relevantINSERT,UPDATE,SELECTstatements.TaskDAO.java— Add any new method signatures to the interface.TaskService.java— Add validation or business logic for the new field.TaskController.java— Add a method that calls the service and triggers a view refresh.TaskView.java— Add the UI element and wire its action to the controller method.style.css— Add styles for any new UI elements.
Rule: Never add SQL to
TaskServiceorTaskController. Never add business logic or UI code toTaskDAOImpl. The layer boundaries are the architecture — crossing them breaks the MVC pattern.
| ID | Severity | Description | Workaround |
|---|---|---|---|
| BUG-01 | Medium | Window can be resized smaller than the form, causing overlap | Avoid resizing below ~800×500px |
| BUG-02 | Medium | tasks.db is created in the working directory, which varies by launch method |
Launch from a consistent directory |
| BUG-03 | Low | Red border on title field persists briefly when reopening the edit dialog | Re-type the title to clear it |
| BUG-04 | Low | Stats bar does not update when the status filter changes | Change the filter twice to force a refresh |
| BUG-05 | Low | Editing a task does not preserve its isComplete state |
Re-toggle after editing if needed |
| BUG-06 | Low | Row colour highlight may be overridden on selected overdue rows | Expected — selection style takes priority |
- Task priorities (Low / Medium / High)
- Column sorting by clicking table headers
- Keyboard shortcuts (
Ctrl+N,Delete,Ctrl+E) - Persist window size between sessions
- Double-click a row to open the edit dialog
- Task categories / tags
- Due date reminder dialog on launch
- Live search bar
- Dark mode toggle
- Export task list to CSV
- Multi-user support with PostgreSQL
- Cloud sync (Google Drive / Dropbox)
- Recurring tasks
- OS system tray notifications
- REST API mode via Spring Boot
This project is provided for educational purposes only as part of the course 26W-CST8411 - Information Systems Development and Deployment at Algonquin College, Ottawa, ON, Canada.