Validate preview sessions against real classpath and module-path fixtures
This commit is contained in:
@@ -100,6 +100,8 @@ FXML previews overlay the owning host's current parent and open Component drafts
|
||||
|
||||
## Discovery and preview API
|
||||
|
||||
Work package 6 now qualifies the [development API and target adapter](preview-target-fixtures.md) against real classpath/module-path fixtures. Session cleanup is cooperative; a fresh target JVM is required to release NeitzelLib process-wide Model/ViewModel state.
|
||||
|
||||
Metadata listing must not construct Models or invoke Controller methods. Separate example descriptors (stable IDs, display labels, compatible Model/View information and declared capabilities) from runtime construction. Generated descriptor metadata or equivalent non-constructing discovery must be tested; calling arbitrary provider initialization merely to list examples does not satisfy this boundary.
|
||||
|
||||
Selecting an example creates a fresh owned preview session with its Model graph and explicitly configured services. Provide readiness and cleanup hooks. Ordinary examples become ready after load/CSS/layout; asynchronous examples signal readiness subject to cancellation/timeout. Construction, services, Controller actions and cleanup execute only in the target JVM. Verify the adapter against NeitzelLib's actual injection/loading lifecycle before publishing Java signatures.
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
# Preview API and target adapter qualification
|
||||
|
||||
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.
|
||||
@@ -1,6 +1,6 @@
|
||||
# NeitzelFXDesigner repository bootstrap plan
|
||||
|
||||
Status: repository foundation implemented by the initial commit; work package 2 has a verified development artifact; work package 3 implements the module/service foundation; work package 4 implements configuration and protocol validation; work package 5 implements Build and Refresh with immutable snapshots; work packages 6–7 remain planned. Consolidated 2026-11-12. Scope is the ordered implementation start for the [accepted initial contract](initial-project-contract.md); the initial commit creates the foundation only and does not publish a library release.
|
||||
Status: repository foundation implemented by the initial commit; work package 2 has a verified development artifact; work package 3 implements the module/service foundation; work package 4 implements configuration and protocol validation; work package 5 implements Build and Refresh with immutable snapshots; work package 6 validates the preview API and target adapter with real fixtures; work package 7 remains planned. Consolidated 2026-11-12. Scope is the ordered implementation start for the [accepted initial contract](initial-project-contract.md); the initial commit creates the foundation only and does not publish a library release.
|
||||
|
||||
## Starting-point evidence before bootstrap
|
||||
|
||||
@@ -74,6 +74,8 @@ Resolve scoped Maven builds, preview source arrangements, explicit save/cancel a
|
||||
|
||||
### 6. Validate the preview API and target adapter against real fixtures
|
||||
|
||||
Implemented: resource-only discovery, typed sessions, real NeitzelLib loading/rendering and 24 classpath/module-path process checks. See [qualification and lifecycle limits](preview-target-fixtures.md). Library-held Model/ViewModel state requires a fresh JVM per session; external shutdown enforcement remains work package 7.
|
||||
|
||||
Add classpath/module-path Maven fixture applications using NeitzelLib artifacts. Implement non-constructing descriptor discovery and typed provider/session lifecycle against the real library. Test fresh Models/services, readiness, cleanup, invalid attributes and write-back. Freeze public Java signatures only after these tests establish the adapter contract.
|
||||
|
||||
**Exit:** standalone target-side tests pass without Kit/IntelliJ dependencies leaking into application-facing artifacts; both preview source arrangements are represented.
|
||||
|
||||
Reference in New Issue
Block a user