Skip to main content

Developer guide

This guide is for you if you want to build njMule from its sources, change it, translate it, package it or drive it from your own programs through its remote-control API. If you only want to use njMule, the user guide is the place to start.

njMule is a Java 25 re-implementation of eMule's networks (eD2K and Kad 2), compatible with the eMule network and licensed under the GPL 3.0 or later. One engine without any user interface (njmule-core) runs as a GraalVM native executable that is also the command line. One interface (njmule-ui), written for the browser, drives it only through its remote-control API: in the desktop window, a small Tauri shell that starts the engine, and as the web interface the engine serves.

Technology stack​

AreaWhat njMule uses
Language and buildJava 25 (JPMS modules), Gradle through the Gradle Wrapper, a convention plugin of its own in build-logic/
Enginevirtual threads, Bouncy Castle, Guava, Jackson 3, Eclipse Jetty 12 (HTTP client and server), Kwik (QUIC), Angus Mail (e-mail notifications), semver4j, Apache Commons Compress and XZ for Java (update packages)
Remote-control APIan OpenAPI 3.2 document, validated with the networknt JSON Schema validator, served by Jetty
Command line and loggingpicocli, SLF4J with Logback
InterfaceVue 3 in TypeScript, built with Vite; Reka UI, TanStack Table and TanStack Virtual; openapi-typescript and openapi-fetch for the API, eventsource-parser for its events; its own SVG line icons and the colours of the AtlantaFX themes
Desktop windowTauri 2 in Rust, with its single-instance, deep-link, dialog, opener, window-state and notification plugins
Web interfaceJetty, with a login page, sessions and form tokens, serving the interface and the API
Native executablesGraalVM Community Native Image 25.0.4.1.1 (native-image); a small C service host on Windows
TestsJUnit (Jupiter) with AssertJ, jqwik for property-based tests, Jimfs, openapi-parser; Vitest with happy-dom for the interface; cargo test for the desktop window
Quality gatesSpotless with palantir-java-format, Checkstyle, Error Prone, JaCoCo, SpotBugs with FindSecBugs, SonarQube Cloud; Prettier and vue-tsc for the interface; cargo fmt and Clippy for the desktop window
PackagesWiX 5 (Windows MSI), nfpm (deb and rpm), codesign and hdiutil (macOS), a shell script for the Synology package, Docker
DocumentationDocusaurus 3.10 with the OpenAPI docs plugin; its screenshots taken with Playwright

Every library and plugin version of the Java build lives in one file, gradle/libs.versions.toml; the npm packages and the Rust crates are pinned in their own lock files: see Dependencies.

Repository layout​

PathContent
njmule-core (module org.njmule.core)the engine: protocols, files, persistence, networking, and the remote-control API; no dependency on any interface
njmule-app (module org.njmule.app)the headless launcher and command line, the Logback set-up, the Windows service commands and their service host
njmule-uithe interface of the desktop window and of the web interface (Vue 3, TypeScript, Vite), with its translations (i18n/) and country flags (flags/)
njmule-desktopthe desktop window: a Tauri 2 shell in Rust (src-tauri/) that starts the engine and shows the interface
njmule-http (module org.njmule.http)the web interface on Jetty (password, sessions, form tokens), which serves the interface and the core's remote-control API, and the desktop window's control endpoint
njmule-testkit (module org.njmule.testkit)test doubles shared by the modules (a fake server, a fake peer, free ports) and the end-to-end tests
njmule-benchJMH benchmarks; a classpath build so that it reaches internal core packages; never distributed
websitethis documentation site (Docusaurus): docs/ is the user guide, developer/ this guide
build-logic/the Gradle convention plugin every Java module applies (njmule.java-conventions)
gradle/libs.versions.toml, verification-metadata.xml and the Gradle Wrapper
config/the license header, the Checkstyle and SpotBugs configuration
packaging/Windows installer (WiX), Linux packages (nfpm), macOS bundle metadata, Docker image, Synology package
branding/original artwork: the master SVG and the PNG, ICO and ICNS files made from it
tools/single-file helper programs (icons, flags, translations, update information) and Docker build scripts
.github/the CI, release and documentation workflows, Dependabot, issue and pull request templates
LICENSES/the texts of every license used in the repository (REUSE)

What each module exports​

The Java modules expose only what their module-info.java exports:

  • org.njmule.core exports org.njmule.core.api (the engine facade, events and application information), org.njmule.core.config (preferences and directory layout) and org.njmule.core.remote (the remote-control API, which a front end serves on its HTTP server). Everything else is internal; a few codec packages and org.njmule.core.persist (the preferences as the profile keeps them) are exported to org.njmule.testkit only.
  • org.njmule.app exports org.njmule.app and org.njmule.app.logging, and provides njMule's Logback configurator; org.njmule.app.logging.internal is not exported.
  • org.njmule.http exports org.njmule.http.
  • org.njmule.testkit exports org.njmule.testkit.

njmule-bench is not a module, and njmule-ui, njmule-desktop and website are not Java projects.

Where to start​

  1. Build njMule and run it from the build.
  2. Read the code style and the testing rules: every change keeps to them, and the build checks most of them.
  3. Read Contributing before you open a pull request.
  4. Pick the page of the area you work on: the interface, translations, native images, packaging, releases, benchmarks or this documentation.
  5. To drive njMule from a script or another program, read the remote-control API.