Files
com_r35157_nenjim-hubd-impl…/openspec/specs/javafx-runtime-service/spec.md
T

7.5 KiB

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. Hub configuration MAY select the JavaFX runtime and applications only through explicit known process IDs in dependency-safe order; it SHALL not add configuration to the JavaFX service API. A valid headless Hub configuration MAY omit the runtime and every JavaFX application, in which case the Hub SHALL not construct or initialize the JavaFX runtime.

Scenario: Configured JavaFX consumers follow runtime startup

  • WHEN a valid Hub configuration selects JavaFX applications
  • THEN it lists nenjim.javafx-runtime.service before those applications and the shared runtime is started before they submit UI work

Scenario: Headless configuration omits JavaFX

  • WHEN a valid Hub configuration omits the JavaFX runtime and all JavaFX applications
  • THEN no JavaFX runtime or application process is constructed and the JavaFX toolkit remains uninitialized by Hub startup

Scenario: Runtime boundary is inspected

  • WHEN the delivered service, process implementation, Hub integration, and application constructors are examined
  • THEN only explicit one-time runtime startup, asynchronous task submission, configuration-ordered dependency injection, and optional omission are present