{"id":33376378,"url":"https://github.com/bsels/javafx-maven-plugin","last_synced_at":"2026-04-25T15:01:16.565Z","repository":{"id":325638150,"uuid":"1101431769","full_name":"bsels/javafx-maven-plugin","owner":"bsels","description":"A lightweight Maven plugin based on the JavaFX Maven Plugin with three goals: fxml‑source generates type‑safe Java classes from FXML at compile time; run launches the app for development; jlink builds a minimal self‑contained runtime image. Requires Java 25+, a modular project, and provides config for packages, debugging, logging, native binaries.","archived":false,"fork":false,"pushed_at":"2026-04-18T14:19:35.000Z","size":1062,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-18T14:26:08.997Z","etag":null,"topics":["java","javafx","javafx-maven-plugin","javafx-modules","maven","maven-plugin","plugin","source-code-generation"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bsels.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-21T17:01:04.000Z","updated_at":"2026-04-09T17:23:42.000Z","dependencies_parsed_at":null,"dependency_job_id":"dde86260-acc7-4316-8e86-29e602d0b186","html_url":"https://github.com/bsels/javafx-maven-plugin","commit_stats":null,"previous_names":["bsels/javafx-maven-plugin"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/bsels/javafx-maven-plugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bsels%2Fjavafx-maven-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bsels%2Fjavafx-maven-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bsels%2Fjavafx-maven-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bsels%2Fjavafx-maven-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bsels","download_url":"https://codeload.github.com/bsels/javafx-maven-plugin/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bsels%2Fjavafx-maven-plugin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32265977,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T09:15:33.318Z","status":"ssl_error","status_checked_at":"2026-04-25T09:15:31.997Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["java","javafx","javafx-maven-plugin","javafx-modules","maven","maven-plugin","plugin","source-code-generation"],"created_at":"2025-11-23T01:00:14.165Z","updated_at":"2026-04-25T15:01:16.552Z","avatar_url":"https://github.com/bsels.png","language":"Java","readme":"# javafx-maven-plugin\n\n[![Latest version](https://img.shields.io/github/v/release/bsels/javafx-maven-plugin?color=blue\u0026label=GitHub+Tag\u0026logo=GitHub)](https://github.com/bsels/javafx-maven-plugin/releases)\n[![Maven Central Version](https://img.shields.io/maven-central/v/io.github.bsels/javafx-maven-plugin?color=blue\u0026label=Maven+Central\u0026logo=apachemaven)](https://search.maven.org/artifact/io.github.bsels/javafx-maven-plugin)\n\n[![Push create release](https://github.com/bsels/javafx-maven-plugin/actions/workflows/push-release.yaml/badge.svg)](https://github.com/bsels/javafx-maven-plugin/actions/workflows/push-release.yaml)\n[![Release Build](https://github.com/bsels/javafx-maven-plugin/actions/workflows/release-build.yaml/badge.svg?event=release)](https://github.com/bsels/javafx-maven-plugin/actions/workflows/release-build.yaml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n![Java Version 25](https://img.shields.io/badge/Java_Version-25-purple?logo=data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjIwMHB4IiB3aWR0aD0iMjAwcHgiIHZlcnNpb249IjEuMSIgaWQ9IkNhcGFfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmlld0JveD0iMCAwIDUwMi42MzIgNTAyLjYzMiIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgZmlsbD0iIzAwMDAwMCI+PGcgaWQ9IlNWR1JlcG9fYmdDYXJyaWVyIiBzdHJva2Utd2hpdGVpZHRoPSIwIj48L2c+PGcgaWQ9IlNWR1JlcG9fdHJhY2VyQ2FycmllciIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48L2c+PGcgaWQ9IlNWR1JlcG9faWNvbkNhcnJpZXIiPiA8Zz4gPGc+IDxwYXRoIHN0eWxlPSJmaWxsOndoaXRlOyIgZD0iTTI0MC44NjQsMjY5Ljg5NGMwLDAtMjguMDItNTMuOTkyLTI2Ljk4NS05My40NDVjMC43NTUtMjguMTkzLDY0LjMyNC01Ni4wNjIsODkuMjgxLTk2LjUyOSBDMzI4LjA3NCwzOS40MzEsMzAwLjA1NCwwLDMwMC4wNTQsMHM2LjIzNCwyOS4wNzctMTAuMzc2LDU5LjE0N2MtMTYuNjA5LDMwLjExMy03Ny45MTQsNDcuNzc5LTEwMS43NDksOTkuNjc5IFMyNDAuODY0LDI2OS44OTQsMjQwLjg2NCwyNjkuODk0eiI+PC9wYXRoPiA8cGF0aCBzdHlsZT0iZmlsbDp3aGl0ZTsiIGQ9Ik0zNDUuNzQxLDEwNS44NjljMCwwLTk1LjQ5NCwzNi4zNDctOTUuNDk0LDc3Ljg0OWMwLDQxLjU0NSwyNS45MjgsNTUuMDI3LDMwLjExMyw2OC41MDkgYzQuMTQyLDEzLjUyNS03LjI2OSwzNi4zNDctNy4yNjksMzYuMzQ3czM3LjM2MS0yNS45NSwzMS4xMDUtNTYuMDYyYy02LjIzNC0zMC4xMTMtMzUuMjktMzkuNDc1LTE4LjY1OS02OS41NDQgQzI5Ni42NDYsMTQyLjc5OSwzNDUuNzQxLDEwNS44NjksMzQ1Ljc0MSwxMDUuODY5eiI+PC9wYXRoPiA8cGF0aCBzdHlsZT0iZmlsbDp3aGl0ZTsiIGQ9Ik0yMzAuNTEsMzI0Ljc0OGM4OC4yNDYtMy4xNDksMTIwLjQzLTMwLjk5NywxMjAuNDMtMzAuOTk3IGMtNTcuMDc2LDE1LjU1My0yMDguNjU0LDE0LjUzOS0yMDkuNzExLDMuMTI4Yy0xLjAxNC0xMS40MTEsNDYuNzAxLTIwLjc3Myw0Ni43MDEtMjAuNzczcy03NC43MjEsMC04MC45NTUsMTguNjggQzEwMC43NCwzMTMuNDY3LDE0Mi4zMjgsMzI3LjgzMywyMzAuNTEsMzI0Ljc0OHoiPjwvcGF0aD4gPHBhdGggc3R5bGU9ImZpbGw6d2hpdGU7IiBkPSJNMzU4LjE4NywzNjguNDk0YzAsMCw4Ni4zNjktMTguNDIxLDc3LjgyNy02NS4zMzhjLTEwLjM1NC01Ny4xMTktNzAuNTgtMjQuOTM2LTcwLjU4LTI0LjkzNiBzNDIuNjAyLDAsNDYuNzIyLDI1LjkyOEM0MTYuMzIsMzMwLjA5OCwzNTguMTg3LDM2OC40OTQsMzU4LjE4NywzNjguNDk0eiI+PC9wYXRoPiA8cGF0aCBzdHlsZT0iZmlsbDp3aGl0ZTsiIGQ9Ik0zMTUuNjI4LDM0My42MDFjMCwwLTIxLjc2NSw1LjcxNi01NC4wMTMsOS4zNGMtNDMuMjI4LDQuODUzLTk1LjQ5NCwxLjAxNC05OS42NTctNi4yNTYgYy00LjA5OC03LjI2OSw3LjI2OS0xMS40MTEsNy4yNjktMTEuNDExYy01MS45MjEsMTIuNDY4LTIzLjUxMiwzNC4yMzMsMzcuMzM5LDM4LjQxOGM1Mi4xNTgsMy41NTksMTI5Ljc5MS0xNS41NzQsMTI5Ljc5MS0xNS41NzQgTDMxNS42MjgsMzQzLjYwMXoiPjwvcGF0aD4gPHBhdGggc3R5bGU9ImZpbGw6d2hpdGU7IiBkPSJNMTgxLjczOCwzODguOTQzYzAsMC0yMy41NTUsMC42NjktMjQuOTM2LDEzLjEzN2MtMS4zNTksMTIuMzgyLDE0LjQ5NiwyMy41MTIsNzIuNjUsMjYuOTY0IGM1OC4xMzMsMy40NTEsOTguOTg4LTE1Ljg5OCw5OC45ODgtMTUuODk4bC0yNi4yOTUtMTUuOTYyYzAsMC0xNi42MzEsMy40OTQtNDIuMjM2LDYuOTQ2IGMtMjUuNjI2LDMuNDczLTc4LjE3My0yLjc4My04MC4yNDMtNy41OTNDMTc3LjU1MywzOTEuNjgyLDE4MS43MzgsMzg4Ljk0MywxODEuNzM4LDM4OC45NDN6Ij48L3BhdGg+IDxwYXRoIHN0eWxlPSJmaWxsOndoaXRlOyIgZD0iTTQwNy45OTQsNDQ1LjAwNWM4Ljk5NS05LjcwNy0yLjc4My0xNy4zMjEtMi43ODMtMTcuMzIxczQuMTQyLDQuODUzLTEuMzM3LDEwLjM3NiBjLTUuNTQ0LDUuNTIyLTU2LjA4NCwxOS4zNDktMTM3LjA2MSwyMy41MTJjLTgwLjk1NSw0LjE2My0xNjguODU2LTcuNjE1LTE3MS42MzktMTcuOTkgYy0yLjY5Ni0xMC4zNzYsNDUuMDE4LTE4LjY1OSw0NS4wMTgtMTguNjU5Yy01LjUyMiwwLjY5LTcxLjk2LDIuMDcxLTc0LjA3NCwyMC4wODJjLTIuMDcxLDE3Ljk2OCwyOS4wNTYsMzIuNTA3LDE1My42NywzMi41MDcgQzM0NC4zMzksNDc3LjQ5MSwzOTkuMDQyLDQ1NC42NDcsNDA3Ljk5NCw0NDUuMDA1eiI+PC9wYXRoPiA8cGF0aCBzdHlsZT0iZmlsbDp3aGl0ZTsiIGQ9Ik0zNTkuNTY4LDQ4NS44MTdjLTU0LjY4MiwxMS4wNDQtMjIwLjczNCw0LjA3Ny0yMjAuNzM0LDQuMDc3czEwNy45MTksMjUuNjI2LDIzMS4xMDksNC4xODUgYzU4Ljg4OC0xMC4yNjgsNjIuMzE4LTM4Ljc2Myw2Mi4zMTgtMzguNzYzUzQxNC4yNSw0NzQuNzA4LDM1OS41NjgsNDg1LjgxN3oiPjwvcGF0aD4gPC9nPiA8Zz4gPC9nPiA8Zz4gPC9nPiA8Zz4gPC9nPiA8Zz4gPC9nPiA8Zz4gPC9nPiA8Zz4gPC9nPiA8Zz4gPC9nPiA8Zz4gPC9nPiA8Zz4gPC9nPiA8Zz4gPC9nPiA8Zz4gPC9nPiA8Zz4gPC9nPiA8Zz4gPC9nPiA8Zz4gPC9nPiA8Zz4gPC9nPiA8L2c+IDwvZz48L3N2Zz4=)\n\nA concise Maven plugin that has been inspired from the JavaFX Maven Plugin\n([openjfx/javafx‑maven‑plugin](https://github.com/openjfx/javafx-maven-plugin)) for the `jlink` and `run` goals.\n\n## Features\n\n| Goal              | What it does                                                                                                                                                                                                                                                                       | Typical use‑case                                                                                                                                                                  |\n|-------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| **`fxml-source`** | Converts each **FXML** file in the project into a corresponding **Java source file**. The generated classes expose the UI structure as plain Java code, which can be compiled together with the rest of the project.                                                               | When you want compile‑time safety for FXML bindings, avoid runtime loading of FXML resources, or need to ship a pure‑Java UI without external `.fxml` files.                      |\n| **`jlink`**       | Invokes the **`jlink`** tool to create a **stand‑alone, custom runtime image** that contains only the modules required by the application. The result is a self‑contained directory (or installer) that can be distributed and run on target machines without a pre‑installed JDK. | Packaging a production‑ready JavaFX application that should run out‑of‑the‑box on end‑users’ computers, minimizing size and eliminating the need for a separate JRE installation. |\n| **`run`**         | Executes the project in the development environment using the same launch logic provided by the upstream **JavaFX Maven Plugin**. It assembles the module path, sets up the JavaFX runtime, and starts the main class so you can iterate quickly while coding.                     | During development, to test UI changes, verify module configurations, or debug the application without building a full distribution.                                              |\n\nThese three goals together give you a smooth workflow: generate type‑safe UI code (`fxml-source`), test and develop\nrapidly (`run`), and finally produce a lean, portable executable bundle (`jlink`).\n\n## Requirements—What does the plugin need?\n\n- **Java version**: The codebase must be compiled and run on **Java 25 or later**.\n  This ensures access to the latest language features, module system improvements, and the `jlink` tool enhancements\n  introduced in recent JDK releases.\n- **Modular architecture**: The application is built as a **Java module** (using `module-info.java`).\n  All source files, libraries, and resources must be declared in explicit modules, allowing the JDK to enforce strong\n  encapsulation and reliable configuration at compile time and run‑time.\n- **FXML handling**:\n    - All **FXML files** reference **classes that are part of the compiled classpath** (i.e., they must already be\n      compiled into the module), or that can be compiled without the source code that needs to be generated\n      (optimistic compilation: compiles everything that can be compiled without errors).\n    - The **generic‑type references** used in those FXML files may reside in source code that has **not yet been\n      compiled**; the plugin will generate the necessary Java source files that will require those classes to be\n      part of the compilation classpath.\n\n## fxml-source Maven Goal\n\nThe **`fxml-source`** goal converts JavaFX FXML files into plain‑Java source code during the **`generate‑sources`**\nphase.\nIt is used to reduce runtime dependencies because the JavaFX FXML loader is not needed at runtime.\n\n### What It Does\n\n1. **Scans** one or more user‑specified directories for `*.fxml` files.\n2. **Reads** each file into an intermediate representation (`FXMLReader`).\n3. **Parses** the file into an `fxml.v2` document model (`FXMLDocumentParser`).\n4. **Generates** Java source code (`FXMLSourceCodeBuilder`) that mirrors the FXML hierarchy (fields, methods, imports,\n   resource bundle lookups, etc.).\n5. **Writes/updates** the generated `.java` files (existing files are overwritten) into a configurable output folder\n   and adds that folder to the project’s compiler source roots so the generated classes are compiled with the rest of\n   the project.\n6. **(Optional)** Extends class discovery with an optimistic in‑memory compilation step so the parser can resolve as\n   many project classes as possible even if the project is not fully compiled yet.\n\n### Key Configuration Parameters\n\n| Parameter                            | Property                               | Required?      | Default                                             | Description                                                                                                                                                                                                |\n|--------------------------------------|----------------------------------------|----------------|-----------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `project`                            | `${project}`                           | Yes (injected) | –                                                   | Maven project reference – used to add the generated source directory to the compile classpath.                                                                                                             |\n| `fxmlDirectories`                    | (n/a; XML config)                      | Yes            | –                                                   | One or more `FXMLDirectory` entries that point to directories with `*.fxml` files. Each entry can also define an output package and exclusions (see below).                                                |\n| `resourceBundleObject`               | `javafx.fxml.resourceBundleObject`     | No             | –                                                   | Fully‑qualified name of a resource‑bundle class used for i18n lookups inside the generated code.                                                                                                           |\n| `generatedSourceDirectory`           | `javafx.fxml.generatedSourceDirectory` | Yes            | `${project.build.directory}/generated-sources/fxml` | Destination folder for the generated Java files.                                                                                                                                                           |\n| `includeSourceFilesInClassDiscovery` | `javafx.fxml.include.source.discovery` | No             | `true`                                              | When `true`, the plugin performs an optimistic in‑memory compilation step to include as many project classes as possible in the discovery classpath (helpful when FXML references project types/generics). |\n| `defaultCharset`                     | `javafx.fxml.charset`                  | Yes            | `UTF-8`                                             | Character set used to read the FXML files and to drive parsing/generation.                                                                                                                                 |\n| `addGeneratedAnnotation`             | `javafx.fxml.add.generated.annotation` | No             | `true`                                              | When `true`, the plugin adds an `@Generated` marker to generated sources.                                                                                                                                  |\n\nEach `FXMLDirectory` entry supports:\n\n| `FXMLDirectory` field | Required? | Default      | Description                                                 |\n|-----------------------|-----------|--------------|-------------------------------------------------------------|\n| `directory`           | Yes       | –            | Directory containing FXML files to process.                 |\n| `packageName`         | No        | (no package) | Package for the generated classes from this directory.      |\n| `excludedFiles`       | No        | (empty)      | Paths (relative to `directory`) to exclude from processing. |\n\n### Typical Usage in `pom.xml`\n\n```xml\n\n\u003cbuild\u003e\n    \u003cplugins\u003e\n        \u003cplugin\u003e\n            \u003cgroupId\u003eio.github.bsels\u003c/groupId\u003e\n            \u003cartifactId\u003ejavafx-maven-plugin\u003c/artifactId\u003e\n            \u003cversion\u003e2.0.0\u003c/version\u003e\n\n            \u003cexecutions\u003e\n                \u003cexecution\u003e\n                    \u003cid\u003egenerate-fxml-sources\u003c/id\u003e\n                    \u003cgoals\u003e\n                        \u003cgoal\u003efxml-source\u003c/goal\u003e\n                    \u003c/goals\u003e\n                    \u003cphase\u003egenerate-sources\u003c/phase\u003e\n                    \u003cconfiguration\u003e\n                        \u003cfxmlDirectories\u003e\n                            \u003cfxmlDirectory\u003e\n                                \u003c!-- Where your .fxml files live --\u003e\n                                \u003cdirectory\u003e${project.basedir}/src/main/resources/fxml\u003c/directory\u003e\n\n                                \u003c!-- Package for the generated classes from this directory --\u003e\n                                \u003cpackageName\u003ecom.myapp.ui.generated\u003c/packageName\u003e\n\n                                \u003c!-- Optional: exclude specific files (relative to \u003cdirectory\u003e) --\u003e\n                                \u003cexcludedFiles\u003e\n                                    \u003cexcludedFile\u003elegacy/OldView.fxml\u003c/excludedFile\u003e\n                                \u003c/excludedFiles\u003e\n                            \u003c/fxmlDirectory\u003e\n                        \u003c/fxmlDirectories\u003e\n\n                        \u003c!-- Optional: custom resource bundle --\u003e\n                        \u003cresourceBundleObject\u003ecom.myapp.i18n.Messages\u003c/resourceBundleObject\u003e\n\n                        \u003c!-- Optional: class discovery from project sources (default: true) --\u003e\n                        \u003cincludeSourceFilesInClassDiscovery\u003etrue\u003c/includeSourceFilesInClassDiscovery\u003e\n\n                        \u003c!-- Optional: parsing/generation charset (default: UTF-8) --\u003e\n                        \u003cdefaultCharset\u003eUTF-8\u003c/defaultCharset\u003e\n\n                        \u003c!-- Optional: add @Generated marker (default: true) --\u003e\n                        \u003caddGeneratedAnnotation\u003etrue\u003c/addGeneratedAnnotation\u003e\n                    \u003c/configuration\u003e\n                \u003c/execution\u003e\n            \u003c/executions\u003e\n        \u003c/plugin\u003e\n    \u003c/plugins\u003e\n\u003c/build\u003e\n```\n\n### When to Use It\n\n- You want **type‑safe Java** access to UI components defined in FXML without a manual controller boilerplate.\n- Your project relies heavily on **code generation** for UI scaffolding or wants to keep UI definitions declarative\n  while still benefiting from IDE navigation and refactoring.\n- You need automatic i18n support via a resource bundle that is wired into the generated code.\n\n### Tips \u0026 Gotchas\n\n- **Package name:** If omitted, generated classes end up in the root of the generated‑source folder, which can cause\n  naming collisions.\n- **Classpath:** Ensure any custom JavaFX controls or third‑party libraries used in the FXML are declared as Maven\n  dependencies; otherwise class loading will fail.\n- **Scripts and expressions:** Scripts and expression bindings (e.g., `\u003cfx:script\u003e`, `${...}`) are not supported yet.\n- **Incremental builds:** The plugin does not currently check timestamps, so it regenerates all files on each run.\n  Consider cleaning the generated folder only when necessary.\n- **Use generics:** Generics need to be explicitly declared in the FXML file.\n  This is done by XML comment: `\u003c!-- generic \u003cindex\u003e: \u003cfull.qualified.type\u003e --\u003e`, e.g.\n  `\u003c!-- generic 0: java.lang.Integer --\u003e`.\n- **Declare interfaces:** If the generated class should implement one or more interfaces,\n  you must declare them in the FXML as XML comments.\n  The supported format is:\n    - `\u003c!-- interface: \u003cfully.qualified.InterfaceType\u003e --\u003e`\n    - `\u003c!-- interface: \u003cfully.qualified.InterfaceType\u003e; methods: \u003creturnType\u003e \u003cmethodName\u003e(\u003cparamType\u003e, ...); ... --\u003e`\n\n  If the interface type can be resolved from the classpath, the plugin will reflectively discover its methods,\n  and you can omit the `methods` part.\n  If the interface type cannot be resolved during parsing (e.g., it is not yet compiled and cannot be found via class\n  discovery), you must provide the `methods` signature list in the comment so the generator can still bind method\n  references.\n\n  Example:\n    - `\u003c!-- interface: com.myapp.ui.contracts.HasSave --\u003e`\n    -\n    `\u003c!-- interface: com.myapp.ui.contracts.HasLoad; methods: void load(java.lang.String); java.lang.String title() --\u003e`\n\n### Important changes in V2\n\nThis section describes differences between the current implementation (V2) and the README’s previous state (V1).\n\n- **Configuration shape changed**: V2 uses `fxmlDirectories` (a list of `FXMLDirectory` entries) instead of single\n  `fxmlDirectory` + top‑level `packageName`.\n- **Per-directory exclusions**: V2 adds `excludedFiles` per `FXMLDirectory` to skip specific FXML files.\n- **Source discovery default changed**: V2 enables optimistic class discovery by default via\n  `includeSourceFilesInClassDiscovery` (`javafx.fxml.include.source.discovery`, default `true`).\n- **New generation toggles**: V2 adds `defaultCharset` (`javafx.fxml.charset`) and `addGeneratedAnnotation`\n  (`javafx.fxml.add.generated.annotation`).\n- **Removed/obsolete options**: V1’s `debugInternalModel` and `fxmlParameterizations` are not part of the V2 mojo\n  configuration surface.\n\n### Example FXML File\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\n\u003c?import javafx.geometry.Insets?\u003e\n\u003c?import javafx.scene.control.Label?\u003e\n\u003c?import javafx.scene.control.Spinner?\u003e\n\u003c?import javafx.scene.layout.ColumnConstraints?\u003e\n\u003c?import javafx.scene.layout.GridPane?\u003e\n\u003c?import javafx.scene.layout.RowConstraints?\u003e\n\u003cGridPane hgap=\"4.0\" maxHeight=\"-Infinity\" maxWidth=\"-Infinity\" minHeight=\"-Infinity\" minWidth=\"-Infinity\"\n          prefWidth=\"600.0\" vgap=\"2.0\" xmlns:fx=\"http://javafx.com/fxml/1\" xmlns=\"http://javafx.com/javafx/17.0.12\"\u003e\n    \u003ccolumnConstraints\u003e\n        \u003cColumnConstraints hgrow=\"NEVER\"/\u003e\n        \u003cColumnConstraints hgrow=\"SOMETIMES\" minWidth=\"10.0\" prefWidth=\"100.0\"/\u003e\n    \u003c/columnConstraints\u003e\n    \u003crowConstraints\u003e\n        \u003cRowConstraints minHeight=\"10.0\" prefHeight=\"30.0\" vgrow=\"SOMETIMES\"/\u003e\n        \u003cRowConstraints minHeight=\"10.0\" prefHeight=\"30.0\" vgrow=\"SOMETIMES\"/\u003e\n        \u003cRowConstraints minHeight=\"10.0\" prefHeight=\"30.0\" vgrow=\"SOMETIMES\"/\u003e\n    \u003c/rowConstraints\u003e\n    \u003cchildren\u003e\n        \u003cLabel text=\"Integer spinner:\"/\u003e\n        \u003cLabel text=\"Double spinner:\" GridPane.rowIndex=\"1\"/\u003e\n        \u003cLabel text=\"Enum spinner:\" GridPane.rowIndex=\"2\"/\u003e\n        \u003cSpinner fx:id=\"spinnerInteger\" maxWidth=\"1.7976931348623157E308\" GridPane.columnIndex=\"1\"\u003e\n            \u003c!-- generic 0: java.lang.Integer --\u003e\n        \u003c/Spinner\u003e\n        \u003cSpinner fx:id=\"spinnerDouble\" maxWidth=\"1.7976931348623157E308\" GridPane.columnIndex=\"1\" GridPane.rowIndex=\"1\"\u003e\n            \u003c!-- generic 0: java.lang.Double --\u003e\n        \u003c/Spinner\u003e\n        \u003cSpinner fx:id=\"spinnerEnum\" maxWidth=\"1.7976931348623157E308\" GridPane.columnIndex=\"1\" GridPane.rowIndex=\"2\"\u003e\n            \u003c!-- generic 0: java.time.DayOfWeek --\u003e\n        \u003c/Spinner\u003e\n    \u003c/children\u003e\n    \u003cpadding\u003e\n        \u003cInsets bottom=\"8.0\" left=\"8.0\" right=\"8.0\" top=\"8.0\"/\u003e\n    \u003c/padding\u003e\n\u003c/GridPane\u003e\n```\n\n---\n\nWith this configuration, running `mvn generate-sources` (or any later lifecycle phase) will automatically produce\nready‑to‑compile Java classes that mirror your FXML UI definitions, letting you treat the UI as ordinary Java code while\npreserving the declarative benefits of FXML.\n\n## jlink Maven Goal\n\nThe **`jlink`** goal creates a custom, minimal Java runtime image that contains only the modules required by your JavaFX\napplication.\nIt leverages the JDK’s `jlink` tool and adds JavaFX‑specific handling (native access, launcher scripts, additional\nbinaries, logging configuration, optional ZIP packaging, etc.).\n\n### When to Use It\n\n- You want a **stand‑alone executable** that ships only the Java runtime and the JavaFX modules your app needs—no\n  separate JRE installation required.\n- You need to **reduce the size** of the distribution by stripping debug info, removing header files/man pages, and\n  applying compression.\n- You require **custom launcher scripts** (extra JVM options, additional binaries, command‑line arguments) or a *\n  *pre‑configured logging format**.\n- You want the final image optionally **zipped** for easy distribution.\n\n### Key Configuration Parameters\n\n| Parameter                  | Property                          | Default      | Description                                                                        |\n|----------------------------|-----------------------------------|--------------|------------------------------------------------------------------------------------|\n| `mainClass`                | `javafx.mainClass`                | **required** | Fully‑qualified main class (or `module/name` if it contains a slash).              |\n| `jlinkExecutable`          | `javafx.jlinkExecutable`          | `jlink`      | Path or name of the `jlink` binary.                                                |\n| `jmodsPath`                | `javafx.jmodsPath`                | –            | Directory containing JavaFX `jmod` files.                                          |\n| `jlinkImageName`           | `javafx.jlinkImageName`           | `image`      | Folder name of the generated runtime image.                                        |\n| `jlinkZipName`             | `javafx.jlinkZipName`             | –            | Base name for the optional ZIP archive (`${name}.zip`).                            |\n| `launcher`                 | `javafx.launcher`                 | –            | Name of the launcher script to create (`bin/\u003clauncher\u003e`).                          |\n| `options`                  | –                                 | –            | List of extra JVM options added to the launcher script.                            |\n| `commandlineArgs`          | `javafx.args`                     | –            | Arguments appended to the launcher’s `$@` placeholder.                             |\n| `additionalBinaries`       | `javafx.additionalBinaries`       | –            | Files copied into `bin/` and exposed as `-D\u003cproperty\u003e=./\u003cfile\u003e` in the launcher.   |\n| `stripDebug`               | `javafx.stripDebug`               | `false`      | Adds `--strip-debug` to `jlink`.                                                   |\n| `stripJavaDebugAttributes` | `javafx.stripJavaDebugAttributes` | `false`      | Adds `--strip-java-debug-attributes`.                                              |\n| `compress`                 | `javafx.compress`                 | `0`          | Compression level (`0‑2` or `zip‑0`-`zip‑9`). Invalid values abort the build.      |\n| `noHeaderFiles`            | `javafx.noHeaderFiles`            | `false`      | Adds `--no-header-files`.                                                          |\n| `noManPages`               | `javafx.noManPages`               | `false`      | Adds `--no-man-pages`.                                                             |\n| `bindServices`             | `javafx.bindServices`             | `false`      | Adds `--bind-services`.                                                            |\n| `ignoreSigningInformation` | `javafx.ignoreSigningInformation` | `false`      | Adds `--ignore-signing-information`.                                               |\n| `jlinkVerbose`             | `javafx.jlinkVerbose`             | `false`      | Adds `--verbose`.                                                                  |\n| `loggingFormat`            | `javafx.loggingFormat`            | –            | Overrides `java.util.logging.SimpleFormatter.format` in `conf/logging.properties`. |\n\n### Typical Usage in `pom.xml`\n\n```xml\n\n\u003cplugin\u003e\n    \u003cgroupId\u003eio.github.bsels\u003c/groupId\u003e\n    \u003cartifactId\u003ejavafx-maven-plugin\u003c/artifactId\u003e\n    \u003cversion\u003e2.0.0\u003c/version\u003e\n\n    \u003cexecutions\u003e\n        \u003cexecution\u003e\n            \u003cid\u003ejlink-image\u003c/id\u003e\n            \u003cgoals\u003e\n                \u003cgoal\u003ejlink\u003c/goal\u003e\n            \u003c/goals\u003e\n            \u003cphase\u003eprocess-classes\u003c/phase\u003e\n            \u003cconfiguration\u003e\n                \u003c!-- Mandatory --\u003e\n                \u003cmainClass\u003ecom.example.MainApp\u003c/mainClass\u003e\n\n                \u003c!-- Optional – customise the image --\u003e\n                \u003cjlinkExecutable\u003ejlink\u003c/jlinkExecutable\u003e\u003c!-- path to jlink --\u003e\n                \u003cjmodsPath\u003e${java.home}/jmods\u003c/jmodsPath\u003e\u003c!-- custom JavaFX jmods --\u003e\n                \u003cjlinkImageName\u003emy-app-image\u003c/jlinkImageName\u003e\u003c!-- output folder --\u003e\n                \u003cjlinkZipName\u003emy-app-runtime\u003c/jlinkZipName\u003e \u003c!-- ZIP name (omit to skip) --\u003e\n\n                \u003c!-- Launcher configuration --\u003e\n                \u003clauncher\u003emyapp\u003c/launcher\u003e\u003c!-- name of the launcher --\u003e\n                \u003coptions\u003e\n                    \u003coption\u003e-Xmx512m\u003c/option\u003e\n                    \u003coption\u003e-Dmy.prop=value\u003c/option\u003e\n                \u003c/options\u003e\n                \u003ccommandlineArgs\u003e--theme dark\u003c/commandlineArgs\u003e\n\n                \u003c!-- Binary files to ship alongside the launcher --\u003e\n                \u003cadditionalBinaries\u003e\n                    \u003cadditionalBinary\u003e\n                        \u003cname\u003effmpeg\u003c/name\u003e\n                        \u003clocation\u003e${project.basedir}/native/ffmpeg.exe\u003c/location\u003e\n                        \u003cmappedJavaProperty\u003effmpeg.path\u003c/mappedJavaProperty\u003e\n                    \u003c/additionalBinary\u003e\n                \u003c/additionalBinaries\u003e\n\n                \u003c!-- Image optimisation flags --\u003e\n                \u003cstripDebug\u003etrue\u003c/stripDebug\u003e\n                \u003cstripJavaDebugAttributes\u003etrue\u003c/stripJavaDebugAttributes\u003e\n                \u003ccompress\u003ezip-9\u003c/compress\u003e\u003c!-- 0‑9 or 1/2 (deprecated) --\u003e\n                \u003cnoHeaderFiles\u003etrue\u003c/noHeaderFiles\u003e\n                \u003cnoManPages\u003etrue\u003c/noManPages\u003e\n                \u003cbindServices\u003etrue\u003c/bindServices\u003e\n                \u003cignoreSigningInformation\u003efalse\u003c/ignoreSigningInformation\u003e\n                \u003cjlinkVerbose\u003efalse\u003c/jlinkVerbose\u003e\n\n                \u003c!-- Logging format (applied to conf/logging.properties) --\u003e\n                \u003cloggingFormat\u003e%1$tF %1$tT %4$s %2$s - %5$s%6$s%n\u003c/loggingFormat\u003e\n            \u003c/configuration\u003e\n        \u003c/execution\u003e\n    \u003c/executions\u003e\n\u003c/plugin\u003e\n```\n\n### Example Build Output\n\n```\ntarget/\n ├─ my-app-image/\n │   ├─ bin/\n │   │   ├─ myapp              ← launcher script (Unix)\n │   │   └─ myapp.bat          ← launcher script (Windows)\n │   ├─ conf/\n │   │   └─ logging.properties ← patched format\n │   ├─ lib/…                  ← JavaFX modules + app modules\n │   └─ …\n └─ my-app-runtime.zip         ← optional distribution archive\n```\n\n### Tips \u0026 Gotchas\n\n- **Module Descriptor Required** – `jlink` will fail if the project does not produce a `module-info.class`.\n- **Compression Values** – Only values present in `COMPRES_OPTIONS` (`zip‑0‑zip‑9` or deprecated `0-2`) are accepted; an\n  invalid value stops the build.\n- **Custom `jmodsPath`** – Point this to the directory containing the JavaFX `jmod` files that match the JDK version you\n  are using.\n- **Launcher Naming** – The `\u003clauncher\u003e` name becomes the executable file name under `bin/`.\n- **Additional Binaries** – Each binary is exposed to the application via a system property (`-D\u003cprop\u003e=./\u003cfile\u003e`). Use\n  this to load native libraries at runtime.\n- **ZIP Packaging** – If you omit `\u003cjlinkZipName\u003e`, the image remains unpacked; useful for Docker layers or when you\n  want to ship the directory as‑is.\n\n### Further Reading\n\nOfficial JDK jlink\ndocumentation: [https://docs.oracle.com/en/java/javase/21/docs/specs/man/jlink.html](https://docs.oracle.com/en/java/javase/21/docs/specs/man/jlink.html).\n\n---\n\nAdd the snippet above to your project's pom.xml and run:\n\n```shell\nmvn clean package\n```\n\nThe plugin will generate a minimal Java runtime image containing only the modules your JavaFX application needs,\ntogether with a ready‑to‑use launcher and optional ZIP distribution.\nEnjoy smaller, faster start‑uptimes and a truly self‑contained delivery artifact!\n\n## run Maven Goal\n\nThe **`run`** goal launches a JavaFX application directly from the Maven build lifecycle.\n\n### When to Use It\n\n- Quick local testing of a JavaFX UI without creating a packaged image.\n- Running the application with custom JVM options, debugger attachment, or additional native binaries.\n- Integrating UI tests into a CI pipeline that can start the app in head‑less mode (if the test harness supports it).\n\nThe goal executes during the `process-classes` phase and requires **runtime** dependency resolution.\n\n### Key Configuration Parameters\n\n| Parameter            | Property                    | Default      | Description                                                                      |\n|----------------------|-----------------------------|--------------|----------------------------------------------------------------------------------|\n| `executable`         | `javafx.executable`         | `java`       | Path or name of the Java executable used to launch the app.                      |\n| `attachDebugger`     | `javafx.attachDebugger`     | `false`      | When `true`, starts the JVM with JDWP remote debugging enabled.                  |\n| `debuggerPort`       | `javafx.debuggerPort`       | `5005`       | Port on which the debugger listens (used only if `attachDebugger` is `true`).    |\n| `mainClass`          | `javafx.mainClass`          | **required** | Fully‑qualified main class (or `module/name` if a module descriptor is present). |\n| `loggingFormat`      | `javafx.loggingFormat`      | –            | Overrides `java.util.logging.SimpleFormatter.format` via `-D` system property.   |\n| `additionalBinaries` | `javafx.additionalBinaries` | –            | List of native files to copy and expose as `-D\u003cprop\u003e=\u003cpath\u003e` system properties.  |\n| `options`            | –                           | –            | Extra JVM options (e.g., `-Xmx1g`).                                              |\n| `modulePathElements` | –                           | –            | Resolved module‑path entries (populated by the base mojo).                       |\n| `classPathElements`  | –                           | –            | Resolved class‑path entries (populated by the base mojo).                        |\n| `commandlineArgs`    | `javafx.args`               | –            | Arguments passed to the application’s `main` method.                             |\n| `skip`               | `javafx.skip`               | `false`      | Skip execution of the goal entirely.                                             |\n| `workingDirectory`   | `javafx.workingDirectory`   | –            | Directory where the process is started; defaults to the project base directory.  |\n\n### Typical Usage in `pom.xml`\n\n```xml\n\n\u003cplugin\u003e\n    \u003cgroupId\u003eio.github.bsels\u003c/groupId\u003e\n    \u003cartifactId\u003ejavafx-maven-plugin\u003c/artifactId\u003e\n    \u003cversion\u003e2.0.0\u003c/version\u003e\n\n    \u003cexecutions\u003e\n        \u003cexecution\u003e\n            \u003cid\u003erun-javafx\u003c/id\u003e\n            \u003cgoals\u003e\n                \u003cgoal\u003erun\u003c/goal\u003e\n            \u003c/goals\u003e\n            \u003cphase\u003eprocess-classes\u003c/phase\u003e\n            \u003cconfiguration\u003e\n                \u003c!-- Main entry point --\u003e\n                \u003cmainClass\u003ecom.example.app.MainApp\u003c/mainClass\u003e\n\n                \u003c!-- Use a custom Java executable (optional) --\u003e\n                \u003cexecutable\u003e${java.home}/bin/java\u003c/executable\u003e\n\n                \u003c!-- Enable remote debugging --\u003e\n                \u003cattachDebugger\u003etrue\u003c/attachDebugger\u003e\n                \u003cdebuggerPort\u003e6006\u003c/debuggerPort\u003e\n\n                \u003c!-- Custom JVM options --\u003e\n                \u003coptions\u003e\n                    \u003coption\u003e-Xmx1024m\u003c/option\u003e\n                    \u003coption\u003e-Dmy.property=42\u003c/option\u003e\n                \u003c/options\u003e\n\n                \u003c!-- Pass arguments to the application --\u003e\n                \u003ccommandlineArgs\u003e--mode demo --verbose\u003c/commandlineArgs\u003e\n\n                \u003c!-- Include native binaries (e.g., ffmpeg) --\u003e\n                \u003cadditionalBinaries\u003e\n                    \u003cadditionalBinary\u003e\n                        \u003cname\u003effmpeg\u003c/name\u003e\n                        \u003clocation\u003e${project.basedir}/native/ffmpeg.exe\u003c/location\u003e\n                        \u003cmappedJavaProperty\u003effmpeg.path\u003c/mappedJavaProperty\u003e\n                    \u003c/additionalBinary\u003e\n                \u003c/additionalBinaries\u003e\n\n                \u003c!-- Override logging format (optional) --\u003e\n                \u003cloggingFormat\u003e%1$tF %1$tT %4$s %2$s - %5$s%6$s%n\u003c/loggingFormat\u003e\n\n                \u003c!-- Working directory (defaults to project base) --\u003e\n                \u003cworkingDirectory\u003e${project.basedir}/target/run-dir\u003c/workingDirectory\u003e\n            \u003c/configuration\u003e\n        \u003c/execution\u003e\n    \u003c/executions\u003e\n\u003c/plugin\u003e\n```\n\n### Tips \u0026 Gotchas\n\n- **Running on Windows** – Ensure the `executable` points to the correct `java.exe` (or use the default `java`).\n- **Debugging** – With `attachDebugger=true`, the JVM will suspend until a debugger attaches. Use `mvnDebug` or connect\n  a remote debugger to the specified `debuggerPort`.\n- **Native Binaries** – The plugin copies each binary into the `bin/` folder of the working directory and adds a\n  `-D\u003cprop\u003e=./\u003cfile\u003e` flag, so the application can locate it via `System.getProperty(\"\u003cprop\u003e\")`.\n- **Large Classpaths** – The generated command may exceed OS limits; consider using the `jlink` goal to create a custom\n  runtime image for repeated runs.\n- **Headless CI** – If the CI environment lacks a display, add `-Djava.awt.headless=true` to options or configure a\n  virtual frame buffer (e.g., Xvfb on Linux).\n- _*Skipping Execution_ – Set `-Djavafx.skip=true` on the command line to bypass the run step (useful for multi‑module\n  builds where only some modules need to be executed).\n\n---\n\n\nAdd the snippet above to your project's pom.xml and run:\n\n```shell\nmvn javafx:run\n```\n\nThe console will display the exact command executed by the plugin, for example:\n\n```shell\njava -Djava.util.logging.SimpleFormatter.format=%1$tF %1$tT %4$s %2$s - %5$s%6$s%n \\\n     -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:*6006 \\\n     -Dffmpeg.path=./ffmpeg.exe \\\n     --enable-native-access=javafx.graphics \\\n     -Xmx1024m -Dmy.property=42 \\\n     -cp target/classes:... \\\n     com.example.app.MainApp --mode demo --verbose\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbsels%2Fjavafx-maven-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbsels%2Fjavafx-maven-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbsels%2Fjavafx-maven-plugin/lists"}