Epigram is a simple Java web app that provides a random epigram to the user and lets users submit their own.
The app is packaged with an embedded Jetty server exposing a Jersey (JAX-RS) REST API alongside a static HTML/CSS/JS frontend, backed by a simple CSV file for persistence of epigrams.
- A browser frontend that fetches and displays a random epigram, with a manual refresh and an auto-refresh toggle, and an add page for submitting new entries.
- A backend service which serves static frontend files and provides an Epigram API with the following endpoints:
GET /api/epigram: returns a random epigram as JSON, never repeating the same one twice in a row.POST /api/epigram: adds a new epigram, either as JSON or as an HTML form submission (used by the add page).
- File-based persistence: Backend service loads epigram data from a CSV file on startup and appends new submissions. If the file doesn't exist on startup, it is created with the required header and a default entry.
The project is managed with Gradle, with a primary project app:
core: core model classes, namelyEpigramdomain objectrepo: repository interfaces and implementations, for query and persistence ofEpigramobjectsuseCase: logic classes which perform app behaviour, includingEpigramRandomiserwhich draws a random, non-repeating epigramext: frameworks/external services for app, namely the Jetty-based web serverEpigramJettyServerand Jersey/JAX-RS endpoint descriptionEpigramResourcefor the Epigram APIresources/webapp: static frontend assets (HTML/CSS/JS) for random epigram and add epigram views, served by the web server
- JRE 17+
Pre-built distribution JARs can be found in Releases.
You can run the web app from the distribution JAR:
java -jar epigram.jar [csvRepoFile] [port]The app can be configured with two positional arguments:
csvRepoFile: path to the CSV repository file. If it does not exist, it will be generated in the working directory. Defaults toepigrams.csvif not provided.port: port to bind server to. Defaults to port8080if not provided.
You can also start the server using Gradle wrapper:
./gradlew runBy default this starts the server on port 8080, using epigrams.csv (created in the working directory if it doesn't
already exist) as the data file.
Once running, visit:
- http://localhost:8080/ (random epigram view)
- http://localhost:8080/add.html (add epigram view)
- http://localhost:8080/api/epigram (epigram api endpoint)
Stop the server with Ctrl+C.
Arguments can also be passed with --args with the same positional arguments as per above.
./gradlew run --args="epigrams.csv 8080"The project uses the Shadow plugin to build a "fat" JAR containing the app and all its dependencies:
./gradlew shadowJarOn build, the distribution JAR can be found at app/build/libs/app-all.jar.
The repository file is a simple comma-delimited (',') CSV with the following header row:
text,author,original_work,original_year
textandauthorare required for each entryoriginal_workandoriginal_yearare optional, but must be included as empty cells- For manual entry, ensure fields are enquoted if they contain commas
If the file doesn't exist at startup, it will be generated with this header and a single default entry.
A sample file is included in this repo: epigrams.csv.
./gradlew test