81 lines
6.7 KiB
Markdown
81 lines
6.7 KiB
Markdown
# javafx-runtime-service Specification
|
|
|
|
## Purpose
|
|
TBD - created by archiving change 80-introduce-javafx-runtime-service. Update Purpose after archive.
|
|
## Requirements
|
|
### Requirement: JavaFX runtime service separates use from lifecycle
|
|
`com.r35157.service.javafx.JavaFxRuntimeService` SHALL be a public `NenjimComponent` interface exposing exactly `void runLater(@NotNull Runnable runnable)` and no initialization, shutdown, restart, status, configuration, window-management, event, or lifecycle operation. `com.r35157.service.javafx.impl.ref.JavaFxRuntimeServiceImpl` SHALL implement both that service and the canonical `NenjimProcess`, so one object supplies the ordinary service view and the Hub-owned process view without a separate manager or administration interface.
|
|
|
|
#### Scenario: Consumer receives only the service view
|
|
- **WHEN** an ordinary JavaFX application receives a `JavaFxRuntimeService`
|
|
- **THEN** it can submit non-null JavaFX work but cannot start, stop, restart, configure, inspect, or administer the runtime through that API
|
|
|
|
#### Scenario: One implementation supplies both views
|
|
- **WHEN** one `JavaFxRuntimeServiceImpl` is registered once
|
|
- **THEN** Registry lookup through `JavaFxRuntimeService` and `NenjimProcess` returns the identical object reference
|
|
|
|
### Requirement: JavaFX runtime startup is one-attempt and complete
|
|
The implementation's `start()` SHALL be the only operation that calls `Platform.startup(...)`. It SHALL accept only the first attempt, configure `Platform.setImplicitExit(false)` on the JavaFX startup callback, wait for that callback to complete successfully, and open service availability only before returning successfully. Every repeated attempt SHALL fail with `IllegalStateException`, including after first-attempt failure or interruption. A synchronous or callback initialization failure SHALL propagate with a clear service-startup diagnostic, leave the service unavailable, and SHALL not be retried, recovered, restarted, rolled back, or silently accepted as an externally initialized toolkit.
|
|
|
|
#### Scenario: First startup succeeds
|
|
- **WHEN** JavaFX startup invokes its callback and implicit exit is disabled successfully
|
|
- **THEN** `start()` returns only after that callback completes and the service becomes available
|
|
|
|
#### Scenario: Startup callback has not completed
|
|
- **WHEN** `Platform.startup(...)` has accepted initialization but its callback has not completed
|
|
- **THEN** `start()` has not returned successfully and task submission remains unavailable
|
|
|
|
#### Scenario: Startup fails
|
|
- **WHEN** toolkit initialization or callback configuration fails
|
|
- **THEN** `start()` propagates a clear failure and the service remains unavailable without partial success
|
|
|
|
#### Scenario: Startup is repeated
|
|
- **WHEN** `start()` is called after any earlier attempt began
|
|
- **THEN** it fails with `IllegalStateException` without calling `Platform.startup(...)` again
|
|
|
|
#### Scenario: Last window closes
|
|
- **WHEN** the last JavaFX window closes after successful service startup
|
|
- **THEN** disabled implicit exit keeps the shared JavaFX runtime alive for later submitted work
|
|
|
|
### Requirement: JavaFX task submission is non-null gated and asynchronous
|
|
`runLater(...)` SHALL reject null with `NullPointerException`. Before successful startup and after failed startup it SHALL reject every non-null task with `IllegalStateException` without initializing, starting, or retrying JavaFX and without executing the task. After successful startup it SHALL submit the exact task through `Platform.runLater(...)` and SHALL never execute it synchronously on the caller's thread. Acceptance SHALL make no guarantee that application UI work completes successfully, and exceptions raised by that work SHALL not change the completed runtime startup milestone.
|
|
|
|
#### Scenario: Null task is submitted
|
|
- **WHEN** `runLater(null)` is called in any service state
|
|
- **THEN** it fails with `NullPointerException` identifying the null task
|
|
|
|
#### Scenario: Task is submitted before successful startup
|
|
- **WHEN** a caller submits a non-null task before `start()` succeeds or after its failure
|
|
- **THEN** submission fails with `IllegalStateException` without any JavaFX initialization or synchronous task execution
|
|
|
|
#### Scenario: Task is accepted after startup
|
|
- **WHEN** a non-null task is submitted after successful startup
|
|
- **THEN** the service passes it to `Platform.runLater(...)` for asynchronous execution on the JavaFX Application Thread
|
|
|
|
#### Scenario: Application task fails
|
|
- **WHEN** accepted UI work later throws on the JavaFX Application Thread
|
|
- **THEN** that remains an application failure and does not convert the service's successful startup into a runtime startup failure
|
|
|
|
### Requirement: Modern JavaFX consumers require the shared service
|
|
`EvelynMissionControlImpl`, `NenjimProcessManagerImpl`, `NenjimComposerImpl`, `NenjimTestToolImpl`, `SodaTaskManagerImpl`, and `SuwimoClientImpl` SHALL each require, reject null for, retain, and use a constructor-injected `JavaFxRuntimeService` for JavaFX Application Thread submission. No compatibility constructor, static fallback, direct `Platform.startup(...)`, lazy initialization helper, or competing initialization flag SHALL remain in the modern component graph. Direct ordinary JavaFX UI API use inside application code SHALL remain valid.
|
|
|
|
#### Scenario: Consumer dependency is null
|
|
- **WHEN** any modern JavaFX implementation is constructed with a null runtime service
|
|
- **THEN** construction fails with `NullPointerException`
|
|
|
|
#### Scenario: Consumer starts UI work
|
|
- **WHEN** any modern JavaFX consumer requests window creation or JavaFX publication
|
|
- **THEN** it submits through its retained service and neither initializes JavaFX nor falls back to static behavior
|
|
|
|
#### Scenario: Static initialization path is inspected
|
|
- **WHEN** modern source is searched after migration
|
|
- **THEN** `com.r35157.libs.javafx.JavaFxRuntime` is absent and only `JavaFxRuntimeServiceImpl.start()` calls `Platform.startup(...)`
|
|
|
|
### Requirement: Deferred JavaFX runtime features remain absent
|
|
The JavaFX runtime service SHALL represent one JVM-wide toolkit and SHALL not implement multiple toolkits, headless emulation, toolkit replacement, shutdown, stop, restart, recovery, supervision, health monitoring, runtime status queries, window discovery or management, configuration, Context resolution, automatic dependency discovery/startup, lifecycle events, or subscriptions. This change SHALL not add `NenjimHub.conf` or configurable autorun.
|
|
|
|
#### Scenario: Runtime boundary is inspected
|
|
- **WHEN** the delivered service, process implementation, Hub integration, and application constructors are examined
|
|
- **THEN** only explicit one-time startup, asynchronous task submission, fixed Hub ordering, and dependency injection are present
|
|
|