Skip to main content
Entwickler Themen
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

8.2.2. Projektkonfiguration und Beispieldaten

Ein Designer-Kontext legt fest, welche Anwendung gebaut wird, welche Maven-Profile gelten und welche Laufzeiten verwendet werden. Diese gemeinsamen Angaben werden versioniert. Rechnerabhängige JDK- und Werkzeugpfade bleiben lokal.

Die gemeinsame Konfiguration

Die Datei neitzel-fx-designer.json liegt im Stamm des Maven-Reaktors. Das Referenzbeispiel verwendet folgenden Kontext:

{
  "schemaVersion": "1.0",
  "contexts": {
    "person-desk": {
      "applicationModule": "fx-example",
      "mavenProfiles": ["designer-preview"],
      "launchMode": "classpath",
      "buildRuntime": "java21",
      "targetRuntime": "java21",
      "preview": {
        "sourceSet": "test",
        "provider": "de.neitzel.fx.example.preview.DeskPreviewProvider",
        "defaultExample": "desk"
      }
    }
  }
}

Bei mehreren Kontexten wird einer ausdrücklich gewählt. Pfade und Modulauswahl müssen innerhalb des Reaktors liegen. Unbekannte Felder oder nicht unterstützte Schema-Versionen werden nicht stillschweigend ignoriert.

Einstellung Bedeutung
applicationModule Anwendungsmodul relativ zum Reaktor-Stamm
mavenProfiles Für den Build gewählte Maven-Profile
launchMode classpath oder module-path
buildRuntime, targetRuntime Logische Namen für die lokale JDK-Zuordnung
buildJava, targetJava Optionale Anforderung an die Java-Hauptversion
requiredCapabilities Ausdrücklich benötigte Fähigkeiten des Workers beziehungsweise der Laufzeit
preview.sourceSet test oder module; bei module ist preview.module erforderlich
preview.provider Vollständiger Klassenname des Providers für die allgemeine Beispielauswahl
preview.defaultExample, preview.examples Standardbeispiel beziehungsweise Einschränkung der Auswahl
preview.requestTimeoutSeconds Zeitgrenze für Anfragen, 1 bis 300 Sekunden
preview.readinessTimeoutSeconds Zeitgrenze für asynchrone Bereitschaft, 1 bis 300 Sekunden
modulePath Nur bei module-path: entryModule sowie optionale addReads und addOpens

Die vollständigen Regeln stehen im Designer-Repository unter designer-contracts/src/main/resources/schema/configuration-1.0.json. Für eine modulare Anwendung gelten zusätzlich deren normale Zugriffsregeln für FXMLLoader und Injection. Der Designer ergänzt keine pauschalen --add-opens, um fehlerhafte Modulkonfigurationen zu verdecken. Die vorhandenen Classpath- und Modulpfad-Testanwendungen zeigen die geprüften Varianten.

Lokale Laufzeiten und Host-Einstellungen

Die ignorierte Datei .neitzel-fx-designer/runtimes.json ordnet die logischen Namen vollständigen JDK-Installationen zu:

{
  "schemaVersion": "1.0",
  "runtimes": {
    "java21": {
      "build": "/absoluter/pfad/zum/jdk-21",
      "target": "/absoluter/pfad/zum/jdk-21"
    }
  }
}

Build-JDK und Ziel-JDK können getrennt gewählt werden. Die Java-Laufzeit des Editors ist eine dritte Rolle. Eine gebündelte Host-Laufzeit ersetzt deshalb nicht die JDK-Zuordnung des Projekts.

Die danebenliegende host.properties enthält configuration, context, settings, maven und tools. Relative Pfade beziehen sich auf diese Datei. tools nennt die JARs für designer-target-tools, designer-contracts und designer-preview-api, getrennt durch den plattformspezifischen Klassenpfadtrenner. Der Schnellstart erzeugt diese Angaben für das Referenzbeispiel. Ein grafischer Projektassistent ist dafür nicht notwendig.

Das Model einer View angeben

Eine Processing Instruction beschreibt, welches Model die View bearbeitet:

<?neitzel-model com.example.Person?>

Sie wird vom normalen FXMLLoader ignoriert. Sie erzeugt kein Model und ersetzt weder Controller noch die ViewModel-Auswahl zur Laufzeit. Der Designer verwendet sie für die gezielte Property- und Binding-Erkennung. Für den FXML-Namensraum wird xmlns:fx="http://javafx.com/fxml/1" verwendet.

Die Erkennung liest kompilierte Signaturen oder optionale generierte Metadaten. Sie konstruiert dabei keine Models und führt keine Getter aus. Nach Änderungen an Java-Klassen oder Konfiguration ist ein neuer erfolgreicher Build notwendig.

PreviewProvider und PreviewSession

Die kleine Abhängigkeit de.neitzel.fxdesigner:designer-preview-api:0.1.0-SNAPSHOT gehört vorzugsweise mit Test-Scope in ein optionales Profil. Ein Provider implementiert PreviewProvider<Model, ApplicationContext>. Sein öffentlicher parameterloser Konstruktor und open(exampleId) werden erst nach Auswahl im Zielprozess ausgeführt.

Das folgende Fragment zeigt den Vertrag. Person, MyApplication und createSamplePerson() gehören zur eigenen Anwendung. Vollständige, kompilierbare Implementierungen stehen im Beispiel unter fx-example/src/designer/java/de/neitzel/fx/example/preview.

import de.neitzel.fxdesigner.preview.PreviewProvider;
import de.neitzel.fxdesigner.preview.PreviewSession;
import de.neitzel.injection.ApplicationContext;

public final class PersonPreview
        implements PreviewProvider<Person, ApplicationContext> {
    public Class<Person> modelType() {
        return Person.class;
    }

    public PreviewSession<Person, ApplicationContext> open(String id) {
        if (!id.equals("person")) {
            throw new IllegalArgumentException(id);
        }
        Person model = createSamplePerson();
        ApplicationContext context = new ApplicationContext(MyApplication.class);
        return new PreviewSession<>() {
            public Person model() { return model; }
            public ApplicationContext context() { return context; }
            public void close() {
                // Eigene Dienste, Timer und Listener freigeben.
            }
        };
    }
}

Jeder Aufruf erhält einen neuen Model-Graphen und neue zugehörige Dienste. Wenn open fehlschlägt, räumt der Provider bereits angelegte Ressourcen selbst auf. Die Methode ready() wird nach dem Laden der View und nach CSS/Layout auf dem FX-Thread aufgerufen. Asynchrone Vorbereitungen werden über die zurückgegebene CompletionStage gemeldet; der FX-Thread darf dabei nicht blockiert werden.

close() wird auf dem FX-Thread einmal aufgerufen, auch nach Lade- oder Bereitschaftsfehlern. Bei einem erzwungenen Prozessende ist kooperatives Aufräumen nicht garantiert. Beispieldienste sollten deshalb bewusst ohne reale Konten, unbeabsichtigte Netzwerkaktionen oder dauerhafte Datenänderungen auskommen.

Im Referenzbeispiel erzeugen DeskPreviewProvider, AddressPreviewProvider und NotePreviewProvider die benötigten Daten. Der eigenständige Row-Preview bereitet auch den Zustand des übergeordneten Controllers vor, den seine Entfernen-Aktion braucht. Er darf nicht voraussetzen, dass vorher eine andere View geöffnet wurde. Das Beispiel öffnet im Preview keinen Message-Popup-Dienst.

Beispiele ohne Ausführung entdecken

Die Zuordnung liegt als Ressource unter META-INF/neitzel-fx-designer/examples.properties:

format=1
count=1
example.0.id=person
example.0.label=Person sample
example.0.modelType=com.example.Person
example.0.providerClass=com.example.PersonPreview
example.0.viewResource=com/example/Person.fxml
example.0.componentPackage=com.example

Diese Beschreibungen können gelesen werden, ohne einen Provider zu konstruieren. Die dokumentbezogene Auswahl berücksichtigt die FXML-Ressource. Dadurch findet AddressForm.fxml ihr eigenes Beispiel, obwohl der Projektkontext den Desk-Provider als allgemeine Vorgabe nennt.

Eine neu erzeugte FXML-Datei benötigt ebenfalls eine passende Beschreibung, bevor eine interaktive Vorschau für sie ausgewählt werden kann. Der Formulargenerator erzeugt keine Provider oder Beispieldaten automatisch.