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.5. Model-Metadaten, ViewModels und Views generieren

Drei Vorgänge greifen auf dieselbe Model-Beschreibung zurück: Metadaten für die Erkennung, optional generierte Java-ViewModels und ein geprüft erzeugtes FXML-Formular. Sie bleiben unabhängig voneinander. Das Personenbeispiel erzeugt Metadaten, behält aber sein handgeschriebenes PersonViewModel.

Model-Metadaten im Build

Der Maven-Compiler erhält de.neitzel.fxdesigner:designer-model-processor:0.1.0-SNAPSHOT als Annotation Processor. Bestehende Prozessoren, beispielsweise Lombok, bleiben dabei erhalten. Die Auswahl gehört in die versionierte Buildkonfiguration:

<configuration>
  <annotationProcessorPaths>
    <path>
      <groupId>de.neitzel.fxdesigner</groupId>
      <artifactId>designer-model-processor</artifactId>
      <version>0.1.0-SNAPSHOT</version>
    </path>
  </annotationProcessorPaths>
  <compilerArgs>
    <arg>-Adesigner.models=com.example.Person,com.example.Address</arg>
  </compilerArgs>
</configuration>

Annotation Processing muss aktiviert sein. Das Beispielprofil setzt dafür proc=full, weil das normale Beispiel es deaktiviert. Die Ressourcen entstehen unter META-INF/neitzel-fx-designer/models/ im Klassenausgabeverzeichnis und später im JAR.

Beschrieben werden geeignete öffentliche les- und schreibbare JavaBean-Attribute, geerbte Properties und deklarierte Collection-Elementtypen. Der Prozessor konstruiert keine Models und ruft keine Getter auf. Nur Typen des aktuellen Quell-Kompilierschritts werden ausgegeben, damit Testkompilierung und abhängige Module keine doppelten Ressourcen erzeugen.

Die Zielerkennung bevorzugt diese Metadaten und prüft sie gegen die kompilierten Signaturen. Ohne Metadaten nutzt sie die vorhandene Signaturerkennung. Vorhandene, aber fehlerhafte, doppelte oder veraltete Metadaten sind ein Fehler und werden nicht stillschweigend ersetzt. Beliebige BeanInfo-Semantik und unklare generische Typen werden nicht erraten.

Nach entfernten oder umbenannten Properties und geänderter Prozessorauswahl ist außerhalb des Designers ein sauberer Build notwendig. Build and Refresh führt diesen bereits isoliert aus. Metadaten sind weder Model-Instanzen noch eine zusätzliche Laufzeitabhängigkeit der Anwendung.

Java-ViewModels erzeugen

Weitere Compiler-Optionen aktivieren die Klassenerzeugung:

<arg>-Adesigner.viewModels=true</arg>
<arg>-Adesigner.viewModelModels=com.example.Person,com.example.Address</arg>
<arg>-Adesigner.generatedPackage=com.example.generated</arg>
<arg>-Adesigner.viewModelDefaults=com.example.Person=com.example.CustomPersonViewModel</arg>

viewModelModels wählt optional eine Teilmenge aus designer.models; ohne Angabe werden alle ausgewählten Models verwendet. Auch viewModelDefaults ist optional. Ohne eigenen Standard wird die jeweilige generierte Klasse verwendet.

Unter target/generated-sources/annotations entstehen Klassen mit typisierten Property- und Zugriffsmethoden. Sie greifen auf die bereits gespeicherten NeitzelLib-Properties zurück. Es gibt keine zweite Property-Tabelle oder getrennte Model-Identität. Geschachtelte ViewModels und beobachtbare Sammlungen behalten die Laufzeitregeln der Bibliothek bei.

Generierte Quellen werden nicht von Hand geändert. Eigene Methoden gehören in eine gewöhnliche Unterklasse der generierten Basisklasse. Ein vorhandenes eigenes ViewModel, das nur von der nicht generischen Klasse ViewModel erbt, kann nicht unverändert als Unterklasse einer neuen generierten Basis registriert werden. Die Laufzeitdetails erläutert Generierte ViewModels in NeitzelLib.

Registry und modulare Anwendungen

Die generierte GeneratedViewModelRegistry beschreibt die Standards, ohne dass Registry-Objekte konstruiert werden müssen. Classpath-Builds erhalten den Service-Deskriptor automatisch. Ein benanntes Modul muss den Provider und den nötigen Zugriff ausdrücklich deklarieren, beispielsweise:

provides de.neitzel.fx.view.ViewModelRegistry
    with com.example.generated.GeneratedViewModelRegistry;
exports com.example.generated;
opens com.example.generated to fx;

Die sonstigen Model-, Controller- und FXMLLoader-Zugriffe bleiben zusätzlich erforderlich. Eine kompatible ausdrückliche @ViewModelClass-Auswahl hat vor der ersten Erzeugung Vorrang. Widersprüchliche Standards oder inkompatible Klassen werden abgelehnt, statt die Identität eines Models aufzuteilen.

Für beteiligte Module sollten getrennte generierte Packages gewählt werden. Nicht unterstützte generische Model-Deklarationen, Namenskollisionen mit reservierten APIs, unsichere Typverengungen und nicht auflösbare geschachtelte Zuordnungen sind Kompilierfehler. Modulübergreifende geschachtelte Generierung und beliebige BeanInfo-Konfigurationen sind nicht durch die geprüfte Ausbaustufe abgedeckt. Die Auswahl erfolgt über Maven; eine grafische Java-Generierungskonfiguration gibt es derzeit nicht.

Ein neues FXML-Formular prüfen

Nach erfolgreichem Build öffnet Bindings → Generate View den gemeinsamen Formulargenerator. Er erzeugt eine neue bearbeitbare Datei und überschreibt keine bestehende View.

  1. Vollständigen Model-Klassennamen und optional einen vorhandenen Controller eintragen, dann Load Model fields wählen.
  2. Attribute ein- oder ausschließen, anordnen und Beschriftung, Control, Binding-Richtung und Converter prüfen. Discover field choices zeigt passende Components, Rows und Converter.
  3. Für geschachtelte Models eine vorhandene Component auswählen. Model-Sammlungen erhalten Repeat oder Table mit vorhandener Component beziehungsweise Row. Table-Columns werden als geordnete Zeilen attribute | header | optional width angegeben.
  4. Einen neuen benachbarten .fxml-Dateinamen angeben und Review generated View wählen. Sowohl Layoutvorschlag als auch exakter XML-Text werden angezeigt. Fehler verhindern die Erzeugung; Warnungen bleiben sichtbar.
  5. Create reviewed View schreibt genau den geprüften Text und öffnet die Datei im normalen Editor. Danach wird sie wie jede andere View bearbeitet.

Ausgelassene Felder brauchen keine gültige Konfiguration. Eine ausgewählte Component oder Row kann vorab separat geöffnet werden. Ändern sich Auswahl, relevantes Dokument oder Build, wird die bisherige Freigabe ungültig. Die Dateierzeugung selbst ist kein Text-Undo-Befehl; spätere Bearbeitungen besitzen normales Undo/Redo.

Was der Generator übernimmt

Skalare Felder bilden ein zweispaltiges GridPane. Boolean-Werte erhalten zunächst CheckBox, andere skalare Werte TextField; unterschiedliche Typen benötigen einen passenden Converter. Geschachtelte Components und Sammlungen belegen eigene breite Bereiche. Ein leerer Controller-Eintrag nutzt den deklarativen Fallback der Bibliothek.

Unterstützt sind TextField, Label, CheckBox, ListView, Component, Repeat und Table. Der Generator schreibt keine Controller, Ereignismethoden, neuen Component-Klassen, Computed-Bindings oder PreviewProvider. Andere Ausgabeordner als eine benachbarte Ressource sind in dieser Ausbaustufe nicht vorgesehen.

Die neue View ist ein eigenständig gepflegtes Dokument. Es gibt keine Regenerationsbeziehung, die spätere Handänderungen überschreibt. Nach einem neuen Build kann die Ressource ausgeführt werden; für ihre interaktive Vorschau wird zusätzlich eine passende Beispielbeschreibung benötigt.