A concurrent URL health-checker built around Data-Oriented Programming (DOP), functional-style pipelines, and structured concurrency on modern Java.
The design follows one core principle: data stays as data. Domain values (ScanRequest, Outcome, ScanResult) are immutable records and sealed types with no behavior attached; all logic lives in small, composable functions that transform one immutable value into the next.
-
Input — the user adds URLs through the UI, backed by a sealed
RowItem(Pending/Scanned) shown in a singleTableView, updated in place as results arrive. -
Scan trigger — clicking Scan rebuilds
Operator.requestListfrom every row (regardless of prior state, so nothing is ever permanently skipped), then runsOperator.setUp()to build oneCallable<ScanResult>per request. -
Execution —
Operator.executeScan()forks every task into aStructuredTaskScope, joined by a customJoiner(CustomJoin) that routes each result into successes or failures as it completes, and reports individual task-level failures via an injected fail-safe callback rather than crashing the scan. -
Network layer — each request goes out via
java.net.http.HttpClientwith browser-like headers, returning aSuccessorFailOutcome— network errors and malformed URLs are both caught and converted into a normalFailresult rather than throwing. -
Aggregation — once all tasks complete,
Report.summarize()folds the results into aCountStat(total/success/failure counts) alongside the raw success/failure lists. -
Export —
JSON_DTO/CSV_DTOconvert the report intoJSON/CSVrecords, memoized viaLazyConstantso repeated exports don't reconvert, and written out through the OS file picker. -
UI responsiveness — the whole scan runs inside a
javafx.concurrent.Taskon a background thread, so the UI never freezes during network calls; per-row UI updates fromCustomJoin's callback are marshaled back onto the JavaFX Application Thread viaPlatform.runLater.
- Java 26 (structured concurrency /
StructuredTaskScope, virtual threads, sealed interfaces, records, pattern matching) LazyConstant(JEP 526/531, preview) for memoized JSON/CSV export datajava.net.http.HttpClientfor HTTPS requests, with browser-like headers to avoid trivial bot-detection false positives- JavaFX, with scans run via
javafx.concurrent.Taskto keep the UI responsive during network calls - JUnit 5, including real-network integration tests (
@Tag("integration"))
Built incrementally, phase by phase:
- Phase 1 — Core data types (
ScanRequest,Outcome,ScanResult) - Phase 2 — Execute stage (HTTPS request per URL)
- Phase 3 — Concurrent execution via
StructuredTaskScope+ customJoiner - Phase 4 — Aggregate stage (stats over
ExecutionResult) - Phase 5 — Sinks (JSON, CSV export, UI output)
- Phase 6 — Input sources: manual entry via UI (bulk/file import intentionally out of scope)
- Phase 7 — Testing: unit tests for all pure logic + one real-network integration test
- Phase 8 — Bug fixes & decoupling:
CustomJoin/Operatorfailure callbacks injected via constructor (no hardcoded UI dependency), scan moved off the JavaFX Application Thread viaTask, malformed-URL handling
- No bulk/file-based URL import — URLs are entered manually through the UI
- Export destination is user-chosen via the OS file picker; no built-in disk-space handling
./gradlew run
Requires
--enable-previewfor structured concurrency andLazyConstant— make sure yourbuild.gradlecompiler/run tasks pass that flag.
./gradlew test
Integration tests (tagged
integration) make real HTTPS requests and are slower than the unit suite.
This repository is not open source. It's shared publicly for portfolio and informational purposes only.
- 🚫 Do not fork, clone, copy, or reuse this code.
- 🚫 Do not use this code or its contents to train, fine-tune, or evaluate any AI/ML model.
- 🚫 GitHub's "Fork" button does not grant permission — forks remain
subject to the same restrictions as the original repo.
All rights are reserved by the copyright holder. See
LICENSEfor full terms.
Want to use this code for something? Reach out first — open an issue or contact me via my GitHub profile.