Files
NeitzelFXDesigner/docs/preview-target-fixtures.md

74 lines
6.4 KiB
Markdown

# Preview API and target adapter qualification
Implementation history: this page records its original bootstrap work package. The [first connected workflow](first-connected-workflow.md) now supplies worker transport, draft overlays and runnable minimal hosts; historical test counts below remain scoped to that earlier step.
Work package 6 is implemented against the [verified NeitzelLib development artifact](runtime/neitzellib-baseline.md), Java 21 and application JavaFX 21.0.7. This qualifies target-side execution; it does not connect the designer UI, snapshot activation or worker transport. Those remain work package 7.
## Discovery and construction
The dependency-free Java 21 preview API contains:
- `ExampleDescriptor(id, label, modelType, providerClass, viewResource, componentPackage)`.
- `PreviewProvider<M,C>`: `modelType()` and `open(exampleId)`.
- `PreviewSession<M,C>`: `model()`, `context()`, asynchronous `ready()` and `close()`.
The NeitzelLib target adapter requires an `ApplicationContext` context. Providers have public no-argument constructors. They create fresh Models and explicitly configured services after selection, on the target FX thread. They own cleanup of partial allocations when construction throws before returning a session. The adapter owns the returned session and calls its cleanup once on load failure, readiness failure, timeout, cancellation or normal close.
Discovery reads UTF-8 `META-INF/neitzel-fx-designer/examples.properties` resources without loading provider or Model classes. This development metadata contract has format version 1:
```properties
format=1
count=1
example.0.id=standard
example.0.label=Standard person
example.0.modelType=fixture.model.Person
example.0.providerClass=fixture.preview.Examples
example.0.viewResource=fixture/components/Person.fxml
example.0.componentPackage=fixture.components
```
Resources are classloader-relative. Catalogs reject unknown/missing/duplicate keys, duplicate IDs across resources, invalid UTF-8 and unsupported versions. Limits are 1 MiB per catalog, 128 catalogs, 1,024 total examples and 4,096 characters per descriptor field. Discovery returns immutable descriptors ordered by ID. No ServiceLoader factory is invoked to list examples.
After selection the adapter checks provider/Model compatibility, invokes NeitzelLib's real `ViewLoader`, creates a Scene and applies CSS/layout before asking for readiness. Readiness must never block FX. Rendering produces bounded row-major straight-alpha RGBA8 using the target's JavaFX. Structured failures distinguish module access, invalid Model/context/provider/resource, loading, readiness, cancellation, timeout and cleanup. Original exception causes remain available.
These are tested development signatures, not a published API release or a promise of compatibility with every NeitzelLib version.
## Lifecycle boundary established by the fixtures
NeitzelLib's `ViewModels` retains Model/ViewModel identities in a process-wide identity map with no public disposal operation. Closing a session releases provider-owned resources but cannot clear that map. Consequently `TargetPreview` allows **one session per target JVM**, including failed sessions. Every restart and interactive preview needs a fresh process.
The adapter's readiness deadline and cleanup are cooperative FX-thread operations. A blocked constructor, Controller or cleanup hook cannot be interrupted by the adapter. Work package 7 must enforce an external process deadline, bounded graceful shutdown and forced termination using the host-owned lifetime channel. The fixture runner enforces a 30-second process timeout. Session close is not proof that library-held objects have been garbage-collected.
## Classpath and module path
The [fixtures](../integration-fixtures/preview/) are ordinary Maven applications depending on artifacts, without copies of library source or Kit/IntelliJ dependencies:
- Classpath: application in main sources; provider, descriptors and executable checks in test sources.
- Module path: named application, separate named preview module and named check launcher. Application and preview dependencies are declared normally in Maven.
The preview API, contracts and target tools now publish stable `Automatic-Module-Name` manifest entries: `de.neitzel.fxdesigner.preview`, `de.neitzel.fxdesigner.contracts`, and `de.neitzel.fxdesigner.target`. They are automatic modules, not fully modularized libraries. The qualified NeitzelLib artifacts resolve as automatic modules `fx`, `injection` and `core`.
The fixture's Component/Controller package is unconditionally open for NeitzelLib's Reflections package discovery and FXML injection. The Model package opens to `fx` for bean binding access. The provider package exports to the target adapter and check launcher. See the actual fixture module descriptors for the complete requires/exports declarations. Removing either Component openness or Model openness produces a structured `MODULE_ACCESS` failure. No broad command-line `--add-opens` repairs are applied.
This qualifies the boot module layer and these packages, not arbitrary custom module layers or every application package topology.
## Reproduce and evidence
After installing the designer reactor and verified NeitzelLib artifact:
```sh
python3 scripts/check-preview-fixtures.py --target-java-home "$TARGET_JAVA_HOME"
```
The same suite runs from `scripts/check-bootstrap.py`. It builds temporary copies of both fixture reactors with Java 21 and launches 24 target processes, covering 346 assertions:
- Metadata discovery without provider initialization or Model/Controller construction.
- Constructor-injected Components, post-initialization custom attributes, inherited attribute coercion and invalid attributes.
- Named ViewModel selection, Controller handoff, configured services, parent and nested bindings, write-back, shared nested Model/ViewModel identity and distinct Component instances.
- Nonempty rendered images and image-size limits.
- Delayed readiness, timeout, cancellation, factory/load/readiness/cleanup failure and exactly-once cleanup.
- Fresh Models/services in separate JVMs and rejection of session reuse.
- Missing Component and Model module access.
Logs and machine-readable results go to `designer-target-tools/target/preview-fixtures/`. Unit tests additionally validate hostile/malformed metadata. The suite requires a graphical environment capable of initializing JavaFX; macOS is qualified here. It does not validate headless rendering, Windows/Linux packaging, real worker IPC or either host UI.