74 lines
6.4 KiB
Markdown
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.
|