Skip to content

Latest commit

 

History

116 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🎵 Music Playlist Manager

A web application for managing personal music playlists, developed as a university project. The application allows authenticated users to upload songs, organize them into playlists, and play them back via an audio player.

Branches

Branch Description
main Full RIA (Rich Internet Application) implementation using JavaScript modules and XMLHttpRequest for async communication
Andrea-dev HTML-only implementation using Thymeleaf server-side rendering and standard form submissions

Features

  • User registration and login with session-based authentication (cookie + session dual mechanism)
  • Upload songs with metadata: title, artist, album, cover image, publication year, genre, and audio file
  • Create playlists and add songs to them
  • Browse playlists ordered by creation date (descending)
  • View songs in a playlist in a paginated table (5 songs per row), with NEXT/PREV navigation
  • Add songs to existing playlists (only songs not already in the playlist)
  • Reorder songs within a playlist (RIA only)
  • Song detail page with an embedded audio player

Tech Stack

  • Backend: Java (Jakarta Servlets)
  • Database: SQLite (managed via DBeaver)
  • Templating (HTML branch): Thymeleaf
  • Frontend (RIA/main branch): Vanilla JavaScript (ES2015 modules)
  • File storage: Filesystem (media files stored by path, not as BLOBs)

Architecture

The server follows a layered architecture:

Controller (Servlet)
    └── Service
            └── DAO (Database / FileSystem)
  • Controllers extend HttpServlet (or DataBaseServlet when DB access is needed) and handle parameter validation and routing.
  • Services contain business logic and are instantiated per-request for thread safety.
  • DAOs handle data persistence — either via SQLite or the FileSystemDao for media files.

Key Server Components

  • TokenService — Manages user identity via HTTP session and an encrypted HttpOnly cookie (TTL: 1 year), enabling extended sessions across browser restarts.
  • TokenBucketService — Manages a pool of database connections using the Token Bucket pattern, avoiding the overhead of creating a new connection per request while respecting SQLite's thread-safety constraints.
  • TemplateService — Singleton wrapper around the Thymeleaf engine; accepts a template name, request/response, and a data map to render HTML pages.
  • Reader / Sender (RIA only) — Utility classes for deserializing JSON request bodies and serializing Java objects to JSON responses.
  • FileSystemDao — Stores uploaded media files on disk under a <user-id>/<file-name> path structure, keeping the database free of BLOBs and enabling more efficient filesystem queries per user.

Database Schema

Built with SQLite. Media file paths (audio and cover image) are stored as TEXT rather than BLOBs for performance and portability.

-- Users
CREATE TABLE users (
    id       INTEGER PRIMARY KEY AUTOINCREMENT,
    name     TEXT NOT NULL,
    surname  TEXT NOT NULL,
    username TEXT NOT NULL,
    password TEXT NOT NULL
);

-- Predefined music genres
CREATE TABLE genre_type (
    id   INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL
);

-- Songs (owned by a user)
CREATE TABLE song (
    id         INTEGER PRIMARY KEY AUTOINCREMENT,
    name       TEXT NOT NULL,
    audio_path TEXT NOT NULL,
    user_id    INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    album_name TEXT NOT NULL,
    artist     TEXT NOT NULL,
    publication DATE NOT NULL,
    cover      TEXT DEFAULT 'default.png',
    genre      INTEGER NOT NULL REFERENCES genre_type(id)
);

-- Playlists (created by a user)
CREATE TABLE playlist (
    id           INTEGER PRIMARY KEY AUTOINCREMENT,
    name         TEXT NOT NULL,
    user_id      INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    custom_order INTEGER DEFAULT 0,
    date         DATE NOT NULL
);

-- Many-to-many: songs in playlists, with display order
CREATE TABLE playlist_song (
    playlist_id INTEGER NOT NULL REFERENCES playlist(id) ON DELETE CASCADE,
    song_id     INTEGER NOT NULL REFERENCES song(id) ON DELETE CASCADE,
    ui_order    INTEGER NOT NULL,
    PRIMARY KEY (playlist_id, song_id)
);

Pages & Navigation

Page Description
Login / Register Single page toggled via Thymeleaf th:if (HTML) or rendered dynamically (RIA)
Home Lists all user playlists ordered by creation date; navbar links to song/playlist creation
Create Song Form to upload a new song with all metadata and media files
Create Playlist Form to name a playlist and select songs to include
Playlist Paginated song table (5 per row); form to add more songs; links to song detail
Song (Player) Displays full song metadata and an HTML5 audio player

JavaScript Architecture (RIA / main)

The RIA implementation uses ES2015 modules split into two categories:

Router

Exposes get(url, onLoad, onError) and post(url, body, onLoad, onError) — thin wrappers around XMLHttpRequest for communicating with the Java servlets asynchronously.

Templating

Rather than embedding hidden HTML in the page, UI is built programmatically via a custom element(tag, props) function. It wraps document.createElement with an internal clone cache for efficiency, and accepts a children array for nested composition. Pages are generated by IIFE-wrapped functions that keep static structure in their closure, re-populating only dynamic content on each render.

This approach was chosen over the in-page hidden HTML pattern to reduce initial page weight and to prevent users from manually revealing or submitting hidden form fields.


Design Decisions

  • No BLOB storage — Media files are saved to the filesystem under uploads/<user-id>/; the DB stores only paths.
  • SQLite — Chosen for zero-configuration setup, portability, and ease of testing with DBeaver.
  • Playlist orderingui_order (auto-increment) in playlist_song tracks insertion order; the RIA branch additionally supports manual reordering via a dedicated Reorder servlet.
  • Registration — Added beyond the base spec; implemented as a variant of the login page using th:if in Thymeleaf (HTML branch) / conditional rendering (RIA branch).
  • Extended navigation — Song creation and playlist creation were moved to dedicated pages accessible via a navbar, improving UX without adding new actions to the spec.
  • Thread-safe connectionsTokenBucketService pools and recycles SQLite connections with TTL-based cleanup on a background thread.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages