Class SwingWorker<T,V>

java.lang.Object
vaadinx.swing.SwingWorker<T,V>
All Implemented Interfaces:
Runnable, Future<T>, RunnableFuture<T>

public abstract class SwingWorker<T,V> extends Object implements RunnableFuture<T>
Emulator for SwingWorker. Emulator-only per D_timer_swingworker — no surrogate (SwingWorker isn't a Component).

Backed by a per-session pool of the JDK's own shape — ten daemon platform threads over a LinkedBlockingQueue — so an eleventh concurrent worker queues exactly as it does on the desktop (D_worker_platform_threads). Lazy-attached on first execute(), disposed when the session is destroyed (interrupts running workers).

EDT routing: publish(Object[]), process(List), done(), and PCE fires hop from the worker thread to the session's live UI via EHelper.onSessionLiveUI(VaadinSession, Runnable), which resolves the current UI and enters EHelper.callSwing(Runnable), so user callbacks see the same UI.getCurrent() + virtual-thread envelope as any other Swing-side event handler (R_callswing_envelope). PCE fires raised from the EDT itself bypass the hop and run inline (fast path + matches Swing's synchronous PCE-on-EDT delivery).

get() and get(long, TimeUnit) called from the EDT throw IllegalStateException per D_gap_severity_triage case 1 (loom rescue trigger): real Swing deadlocks; we fail-fast with a message naming the cause, preserving the migrator's mental model.

A EmulatorContext — the owning VaadinSession plus the user's browser time zone — is captured at construction (not the UI), so an in-flight worker survives an F5 @PreserveOnRefresh teleport and delivers done()/process() onto the UI that is live at completion time, not the (closed) one it started under. See UiScopedFeaturesF5Test. Constructing with no current session throws IllegalStateException. doInBackground() runs inside EmulatorContext.call(Callable), so SimpleDateFormat / the Calendar emulator format in the user's zone off the EDT rather than the server default.

  • Field Details

  • Constructor Details

    • SwingWorker

      protected SwingWorker()
      Throws:
      IllegalStateException - if no current Vaadin session — SwingWorkers are bound to the session they were constructed in.
  • Method Details

    • doInBackground

      protected abstract T doInBackground() throws Exception
      Background work. Runs on a virtual thread off the EDT.
      Throws:
      Exception
    • process

      protected void process(List<V> chunks)
      EDT-side callback for chunks published via publish(Object[]). Default no-op.
    • done

      protected void done()
      EDT-side callback after doInBackground() returns (success, exception, or cancel). Default no-op.
    • execute

      public final void execute()
      Submits this worker to the per-UI VT executor. Idempotent — second and subsequent calls are no-ops (matches JDK contract: a worker may only be executed once).
    • run

      public final void run()
      Worker body. Drives the state machine: PENDING → STARTED → run doInBackground → DONE → schedule done() on EDT. The finally-block always finalises, so a thrown doInBackground still transitions to DONE and fires done() (matches JDK).
      Specified by:
      run in interface Runnable
      Specified by:
      run in interface RunnableFuture<T>
    • cancel

      public final boolean cancel(boolean mayInterruptIfRunning)
      Cancels the worker. If mayInterruptIfRunning is true and a doInBackground is in flight, the worker thread is interrupted — doInBackground's I/O calls or sleeps see InterruptedException. Returns true unless the worker had already completed.
      Specified by:
      cancel in interface Future<T>
    • isDone

      public final boolean isDone()
      Specified by:
      isDone in interface Future<T>
    • isCancelled

      public final boolean isCancelled()
      Specified by:
      isCancelled in interface Future<T>
    • getState

      public final SwingWorker.StateValue getState()
    • get

      public final T get() throws InterruptedException, ExecutionException
      Blocks until the worker completes; returns its result.

      Allowed from the EDT only when isDone() — that's the canonical done() call site, where the worker's already finished and get() returns immediately without blocking. Throws IllegalStateException if called from the EDT before the worker finishes (D_gap_severity_triage case 1 loom rescue: under Swing this would deadlock the EDT).

      Specified by:
      get in interface Future<T>
      Throws:
      IllegalStateException - if called from the EDT before the worker is done.
      InterruptedException
      ExecutionException
    • get

      public final T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
      Specified by:
      get in interface Future<T>
      Throws:
      IllegalStateException - if called from the EDT before the worker is done (D_gap_severity_triage case 1).
      TimeoutException - if the wait elapses without completion.
      InterruptedException
      ExecutionException
    • publish

      @SafeVarargs protected final void publish(V... chunks)
      Coalescing publish. Appends chunks to a pending list; the first publish since the last drain schedules one EDT-side process(List) call that drains and clears the list. Subsequent publishes before the drain merge into the snapshot the scheduled process(...) will see.
    • setProgress

      protected final void setProgress(int progress)
      Throws:
      IllegalArgumentException - if progress is outside [0, 100] (JDK-faithful).
    • getProgress

      public final int getProgress()
    • firePropertyChange

      public final void firePropertyChange(String propertyName, Object oldValue, Object newValue)
      Fires a PropertyChangeEvent. On-EDT callers fire synchronously (matches Swing's same-thread PCE delivery); off-EDT callers hop via EHelper.onSessionLiveUI(VaadinSession, Runnable) so listeners always run under the session's live UI lock inside a EHelper.callSwing(Runnable) VT continuation (R_callswing_envelope).
    • getPropertyChangeSupport

      public final PropertyChangeSupport getPropertyChangeSupport()
    • addPropertyChangeListener

      public final void addPropertyChangeListener(PropertyChangeListener listener)
    • removePropertyChangeListener

      public final void removePropertyChangeListener(PropertyChangeListener listener)
    • addPropertyChangeListener

      public final void addPropertyChangeListener(String propertyName, PropertyChangeListener listener)
    • removePropertyChangeListener

      public final void removePropertyChangeListener(String propertyName, PropertyChangeListener listener)