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 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.
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.
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.
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.
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.