A desktop UML diagram editor built with Java 17 + JavaFX. You draw diagrams on a canvas, connect them with UML relationships, and save your work as JSON or export it as a PDF.
Built by Zohaib Raffat and Ahmad as a Software Construction & Development (SCD) project.
The app opens on a welcome screen where you pick one of two editing modes:
| Mode | What you can place |
|---|---|
| Class Diagram | Classes (attributes + operations), Interfaces, Enumerations |
| Use Case Diagram | System frame (boundary box), Actors, Use cases |
Both modes share the same canvas engine, so you always get:
- Drag to move any element; the connected lines follow it live.
- Click to select, with a highlight, and Delete Selected to remove an element and everything attached to it.
- Right-click a relationship line to delete just that line.
- Editable labels on relationships — click the text field on a line to name it (e.g. multiplicity or role).
- Change Diagram Type to go back to the welcome screen (warns about unsaved changes first).
| Class diagram | Use case diagram |
|---|---|
| Association | Association |
| Aggregation (hollow diamond) | Include |
| Composition (filled diamond) | Extend |
| Inheritance (hollow triangle) |
Drawing a relationship is a two-click mode: press the relationship button, click the source element, then click the target element. Arrowheads and diamonds are drawn automatically and re-anchor to the element borders as you drag things around.
- Save Diagram → writes a
.jsonfile containing every diagram plus every relationship (type, source class name, target class name, label text). - Load Diagram → clears the canvas and rebuilds the diagrams and their relationships from a
.jsonfile. - Save as PDF → snapshots the canvas and embeds it, scaled to fit, into a one-page PDF via iText.
| JDK | 17 or newer. Verified working on JDK 25 (Temurin/Homebrew). No separate JavaFX SDK needed — JavaFX comes in as a Maven dependency. |
| Maven | Not required — use the bundled wrapper (./mvnw). It downloads Maven 3.8.5 on first run. |
| Network | Needed on the first build to fetch dependencies. |
| OS | macOS, Windows, Linux. JavaFX pulls the right native classifier for your platform automatically. |
This is a GUI application — it needs a real desktop session. It will not run over a plain SSH shell or in a headless container.
cd UML-Editor
chmod +x mvnw # first time only — the wrapper ships without the executable bit
./mvnw clean javafx:runThe javafx-maven-plugin puts JavaFX on the module path for you and launches
org.example.scd_uml_project.HelloApplication. An 800×600 window titled "UML Editor" appears.
On Windows use mvnw.cmd clean javafx:run (no chmod needed).
Open UML-Editor/pom.xml as a Maven project in IntelliJ IDEA or VS Code, let it import,
then run HelloApplication. Because the project is modular (src/main/java/module-info.java),
the IDE handles the module path automatically — no --add-modules VM arguments required.
./mvnw clean compile # main sources only — works
./mvnw clean package -Dmaven.test.skip=true # produces target/SCD_UML_project-1.0-SNAPSHOT.jar
./mvnw packageand./mvnw testfail on their own — see Known issues below. Note that-DskipTestsis not enough; you need-Dmaven.test.skip=true, which skips test compilation too.
The produced jar is a plain jar: it has no Main-Class in its manifest and does not bundle
JavaFX, org.json, or iText. java -jar target/SCD_UML_project-1.0-SNAPSHOT.jar will not work.
Use ./mvnw javafx:run or the IDE. Making a runnable jar would require adding a shade/assembly
plugin (or javafx:jlink — see the note about iText below).
These are real, verified against the current code on macOS / JDK 25.
src/test/java/.../HelloControllerTest.java fails testCompile with 5 errors:
| Line | Error |
|---|---|
| 23 | cannot find symbol: variable loader — the loader is named fxmlLoader; the line Parent root = loader.load(); got merged onto the same line as its declaration |
| 52 | cannot find symbol: variable promptForTitle — no such field on HelloController |
| 70, 108 | cannot find symbol: method getLastShownAlert() — no such method on HelloController |
| 95 | selectedDiagram has private access in HelloController |
The test was written against a version of HelloController that exposes test hooks the current
controller does not have. This does not affect running the app — compile and javafx:run
both succeed. To build a jar, skip tests with -Dmaven.test.skip=true. To actually fix it,
either add the missing hooks to HelloController (promptForTitle, getLastShownAlert(),
widen selectedDiagram to protected) or rewrite/remove the test.
The POM declares two different JavaFX releases:
javafx-controls, javafx-fxml, javafx-media → 17.0.6
javafx-base, javafx-graphics, javafx-swing → 21.0.1
JavaFX expects all its modules to be the same version. Maven's nearest-wins resolution keeps both,
so javafx.controls 17 runs on top of javafx.graphics 21. It does launch today, but this is
exactly the setup that produces NoSuchMethodError / NoClassDefFoundError at runtime after a
dependency bump. Align all six on one version (21.0.1 is the safe choice, since it's what graphics
already resolves to).
org.testfx:testfx-core (and transitively hamcrest and assertj) has no <scope>test</scope>,
so a test-only framework lands on the application's runtime module path. testfx-junit5 is correctly
scoped; testfx-core should be too.
Every build prints:
Required filename-based automodules detected: [itextpdf-5.5.13.3.jar].
Please don't publish this project to a public artifact repository!
itextpdf 5.x has no module-info and no Automatic-Module-Name, so its module name is derived
from the filename. module-info.java still does requires itextpdf;, which works for compiling
and running but blocks the javafx:jlink goal the POM is otherwise configured for.
A fresh clone gives permission denied: ./mvnw. Run chmod +x mvnw once (already noted above).
Warning on every build: "location of system modules is not set in conjunction with -source 17 …
may lead to class files that cannot run on JDK 17." Switching the maven-compiler-plugin
config from <source>/<target> to <release>17</release> silences it and makes the JDK-17
target real.
src/main/resources/zoeb_pic.jpeg(and its duplicate underorg/example/scd_uml_project/) is not referenced by any code or FXML — dead weight in the jar.ClassDiagram.fxmlandUseCaseDiagram.fxmlare missing the<?xml version="1.0" encoding="UTF-8"?>prolog thatWelcomePage.fxmlhas. FXMLLoader tolerates it, but it's inconsistent.HelloControlleris a 2,850-line class holding the entire editor. Every relationship type has its own near-duplicatecreate*Line/adjust*LineToBorders/delete*Line/add*DynamicUpdateListenerquartet — the obvious refactor target.
UML-Editor/
├── pom.xml Maven build: JavaFX, org.json, iText, JUnit 5, TestFX
├── mvnw, mvnw.cmd, .mvn/ Maven wrapper (Maven 3.8.5)
└── src/
├── main/
│ ├── java/
│ │ ├── module-info.java module org.example.scd_uml_project
│ │ └── org/example/scd_uml_project/
│ │ ├── HelloApplication.java Entry point — loads WelcomePage.fxml
│ │ ├── WelcomeController.java Diagram-type picker
│ │ ├── HelloController.java The editor: canvas, all tools, save/load/PDF
│ │ ├── DiagramBase.java Interface: toJSON() + getClassName()
│ │ ├── ClassDiagram.java \
│ │ ├── InterfaceDiagram.java | Draggable Pane subclasses
│ │ ├── EnumerationDiagram.java | rendered on the canvas
│ │ ├── UseCaseDiagram.java |
│ │ ├── Actor.java /
│ │ ├── ClassData.java \
│ │ ├── InterfaceData.java | Plain data holders backing
│ │ ├── EnumerationData.java | each diagram type
│ │ ├── UseCaseData.java |
│ │ ├── ActorData.java /
│ │ ├── Relationship.java Type + source + target + label
│ │ └── RelationshipNode.java Group wrapper placed on the canvas
│ └── resources/org/example/scd_uml_project/
│ ├── WelcomePage.fxml
│ ├── ClassDiagram.fxml Left toolbar: Class/Enum/Interface + Comp/Inh/Agg
│ └── UseCaseDiagram.fxml Left toolbar: Actor/Use Case/Include/Extend/Frame
└── test/java/org/example/scd_uml_project/
└── HelloControllerTest.java TestFX — currently does not compile (issue #1)
ClassDiagram.fxml and UseCaseDiagram.fxml both bind to the same HelloController.
Its initialize() only touches the buttons that exist in both files (btnSave, btnLoad,
btnDelete, btnChangeDiagramType, canvasPane), which is why one controller can serve both screens.
- Align the JavaFX versions (issue #2) — cheapest, biggest reduction in future breakage.
- Scope
testfx-coretotest(issue #3). - Fix or delete
HelloControllerTestso./mvnw packageworks unaided (issue #1). - Switch to
<release>17</release>(issue #6). - Add a shade/assembly plugin if a double-clickable jar is wanted, or replace iText 5 with a
real JPMS module (e.g.
com.itextpdf:itext-core7.x / PDFBox) to unlockjavafx:jlink(issue #4).