Project Architecture Overview
The Jukebox project follows a clean Model-View-Controller (MVC) pattern, which is a common architectural pattern in software development. This pattern separates the application into three interconnected components:
- Model: Manages data, logic, and rules of the application
- View: Handles the display and user interface
- Controller: Acts as an intermediary between Model and View, handling user input
Architecture Diagram
┌─────────────────────────────────────────────────────────────────┐
│ JUKEBOX APPLICATION │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │
│ │ MODEL │ │ CONTROLLER │ │ VIEW │ │
│ │ (Data Classes) │◄──►│ (Controller Classes)│◄──►│ (FXML Files)│ │
│ └─────────────────┘ └─────────────────┘ └─────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │
│ │ Database.java │ │ ApplicationWindow│ │ application-│ │
│ │ Album.java │ │ Controller.java │ │ window.fxml │ │
│ │ Song.java │ │ AdminPanelController│ │ │ │
│ │ User.java │ │ ChooseAlbumController│ └─────────────┘ │
│ │ Genre.java │ │ PlayAlbumController│ │
│ └─────────────────┘ │ HomeScreenController│ │
│ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Component Breakdown
1. Model Layer
The Model layer contains the data classes that represent the application's information. These are pure Java classes with no dependencies on JavaFX.
The Database class is a singleton-like object that holds all application data. It's created once in Jukebox.main() and stored in a static field for access throughout the application. This makes it easy to share data between different parts of the program.
2. View Layer
The View layer consists of FXML files that define the user interface declaratively (using XML). Each FXML file corresponds to a screen or component in the application.
- Separates UI design from logic
- Declarative syntax is easier to read and maintain
- Can be designed visually with tools like Scene Builder
- Automatically connects to controller classes
3. Controller Layer
The Controller layer contains Java classes that handle user interactions, manage the view lifecycle, and coordinate with the Model.
In the Jukebox project, controllers communicate through static fields in the Jukebox class. Each controller has a static reference that can be accessed from anywhere:
// In Jukebox.java
public static ApplicationWindowController applicationWindowController;
public static ChooseAlbumController chooseAlbumController;
public static PlayAlbumController playAlbumController;
public static HomeScreenController homeScreenController;
public static AdminPanelController adminPanelController;
public static Database database;
public static Album selectedAlbum;
Application Flow
Here's how the application starts and flows between views:
Application Startup
Jukebox.main()is called when you run the program- It creates a new
Databaseinstance and callsloadData()to load saved data fromdatabase.json - It calls
launch(args)which starts the JavaFX runtime
JavaFX Initialization
- JavaFX calls
Jukebox.start(Stage stage) start()creates the main view by callingApplicationWindowController.createViewInstance()- A
Sceneis created with the view as the root node - The scene is set on the primary stage and the window is shown
View Initialization
ApplicationWindowController.createViewInstance()loadsapplication-window.fxml- The
initialize()method is called automatically - All child views (Home, Choose Album, Play Album, Admin) are created and cached
- The home view is displayed as the initial screen
View Navigation
When a user clicks a button to navigate:
- An event handler in the current controller is called (e.g.,
onHomeButtonClicked) - If coming from Admin Panel, data is auto-saved via
database.saveData() - The
ApplicationWindowControllerclears the container and adds the new view - For Play Album view, the controller is re-initialized to load current album data
Navigation Flow Diagram
┌─────────────────┐
│ HOME SCREEN │
└────────┬────────┘
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────┐ ┌─────────────┐
│ PLAY MODE │ │ ADMIN MODE │ │ (other views)│
│ (Choose Album) │ │ (Admin Panel)│ │ │
└────────┬────────┘ └────────┬────┘ └─────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────┐
│ PLAY ALBUM │ │ (saves data │
│ (Song list) │ │ on exit) │
└─────────────────┘ └─────────────┘
│ │
└────────┬─────────┘
▼
┌──────────────┐
│ HOME SCREEN │
│ (via GO HOME) │
└──────────────┘
The Jukebox uses a single window with a container-based view switching system. Instead of creating multiple windows, different views are added and removed from the same container (VBox with fx:id="container"). This provides a more consistent user experience and is easier to manage.
Data Flow
Understanding how data moves through the application is crucial:
Data Loading
- When the application starts,
Database.loadData()reads fromdatabase.json - Gson deserializes the JSON into a
Databaseobject - The
Databaseobject is stored inJukebox.databasefor global access
Data Display
- Controllers access data from
Jukebox.database - For example,
AdminPanelController.initialize()creates an ObservableList fromJukebox.database.albums - The ListView automatically displays the contents of the ObservableList
Data Modification
- When a user adds, edits, or deletes items, the changes are made directly to the objects in
Jukebox.database - For ObservableLists, changes automatically update the UI
- For non-Observable collections,
refresh()is called to update the display
Data Saving
- Data is saved in several scenarios:
- Manual Save: Clicking "Save All" in Admin Panel calls
database.saveData() - Auto-Save on Navigation: When leaving Admin Panel,
ApplicationWindowControllerautomatically saves Database.saveData()uses Gson to serialize the entire Database object to JSON
Key Architectural Decisions
In a small to medium-sized application like Jukebox, static references provide a simple way for controllers to communicate. Benefits:
- Easy to access from anywhere
- No complex dependency injection framework needed
- Simple to understand for beginners
Trade-off: This approach can make testing more difficult and isn't ideal for very large applications. For production applications, consider using dependency injection or event buses.
FXML provides several advantages:
- Separation of UI design from business logic
- Can be edited with visual tools (Scene Builder)
- Easier to maintain and modify UI without touching code
- Supports CSS styling
Using a single window with view switching:
- Provides consistent user experience
- Easier to manage state and navigation
- Better performance (views are cached and reused)
- Simpler window management
Gson was chosen for persistence because:
- Simple API - easy for beginners to understand
- No configuration needed - just add the JAR file
- Automatically handles complex object graphs
- Human-readable JSON output
Summary
The Jukebox project demonstrates a well-structured JavaFX application using:
- MVC Pattern - Clean separation of concerns
- FXML for Views - Declarative UI definition
- Static References - Simple controller communication
- Single Window Architecture - Consistent user experience
- Gson for Persistence - Easy data serialization
Understanding this architecture will help you as you explore the individual cookbook sections, as each section builds on these foundational concepts.