Class EventBus

java.lang.Object
com.ultikits.ultitools.events.EventBus

public class EventBus extends Object
Central event bus for inter-module communication. Supports sync and async dispatch, annotation and programmatic subscriptions.
Since:
6.2.2
  • Field Details

    • LOGGER

      private static final Logger LOGGER
    • handlers

      private final Map<Class<? extends ModuleEvent>,CopyOnWriteArrayList<HandlerEntry>> handlers
    • asyncPool

      private final ExecutorService asyncPool
    • registrationScopeOwner

      private final ThreadLocal<UltiToolsPlugin> registrationScopeOwner
      The module instance the framework is loading on this thread, if any (#506): set by beginRegistrationScope(UltiToolsPlugin) while a module's container refreshes and its registerSelf() runs, and recorded on every handler registered meanwhile without an explicit owner instance. A ThreadLocal, like TabCompletionManager's scope, so a registration another thread makes during that window is not attributed to the module.
  • Constructor Details

    • EventBus

      public EventBus()
  • Method Details

    • register

      public void register(Class<? extends ModuleEvent> eventType, EventPriority priority, boolean ignoreCancelled, String ownerModule, Method method, Object instance)
      Register an annotation-based handler.
    • register

      public void register(Class<? extends ModuleEvent> eventType, EventPriority priority, boolean ignoreCancelled, String ownerModule, UltiToolsPlugin ownerInstance, Method method, Object instance)
      Register an annotation-based handler and record the module instance that owns it (#506).

      unregisterByOwnerInstance(UltiToolsPlugin) then releases exactly this instance's handlers, whatever name they were filed under. The framework registers every module's @ModuleEventHandler methods this way, so unloading a superseded copy of a module cannot release its replacement's handlers, which share its name.

      Parameters:
      eventType - the event type handled
      priority - the dispatch priority
      ignoreCancelled - whether a cancelled event skips this handler
      ownerModule - the owning module's name, used by unregisterAll(String)
      ownerInstance - the owning module instance; null records none
      method - the handler method
      instance - the bean the method is invoked on
      Since:
      6.3.0
    • subscribe

      public <T extends ModuleEvent> Subscription subscribe(Class<T> eventType, Consumer<T> consumer)
      Register a programmatic handler. Returns a Subscription for manual unsubscribe.
    • subscribe

      public <T extends ModuleEvent> Subscription subscribe(Class<T> eventType, EventPriority priority, boolean ignoreCancelled, String ownerModule, Consumer<T> consumer)
      Register a programmatic handler with full options.

      As of 6.3.0 the handler is recorded against a module instance (#506, #562 item 1): the module the framework is loading on this thread, if any; otherwise the copy listed as loaded under ownerModule (the first listed when more than one is); otherwise none, and it is filed under the name only. Unloading or superseding that copy releases it. Prefer subscribe(Class, EventPriority, boolean, String, UltiToolsPlugin, Consumer) when the module instance is at hand.

    • subscribe

      public <T extends ModuleEvent> Subscription subscribe(Class<T> eventType, EventPriority priority, boolean ignoreCancelled, String ownerModule, UltiToolsPlugin ownerInstance, Consumer<T> consumer)
      Register a programmatic handler and record the module instance that owns it (#506), so unregisterByOwnerInstance(UltiToolsPlugin) releases it whatever name it was filed under. Without an instance, a handler subscribed while the framework loads a module (see beginRegistrationScope(UltiToolsPlugin)) is recorded against that module; one subscribed later is recorded against the copy listed as loaded under ownerModule (PluginManager.findRegistrationOwner(String)), and filed under the name only when no copy is listed under it (#562 item 1).
      Type Parameters:
      T - the event type
      Parameters:
      eventType - the event type handled
      priority - the dispatch priority
      ignoreCancelled - whether a cancelled event skips this handler
      ownerModule - the owning module's name, used by unregisterAll(String)
      ownerInstance - the owning module instance; null records the loading module, if any, otherwise the copy listed under ownerModule, if any
      consumer - the handler
      Returns:
      a subscription for manual unsubscribe
      Since:
      6.3.0
    • unregisterAll

      public void unregisterAll(String moduleName)
      Unregister all handlers owned by a module.
    • unregisterByOwnerInstance

      public void unregisterByOwnerInstance(UltiToolsPlugin ownerInstance)
      Unregister every handler registered with ownerInstance as its owner (#506), whatever module name it was filed under. Handlers registered with a name only are not matched here; unregisterAll(String) releases those.
      Parameters:
      ownerInstance - the module instance being unloaded; null matches nothing
      Since:
      6.3.0
    • releaseForSupersede

      @Internal public Runnable releaseForSupersede(UltiToolsPlugin ownerInstance)
      Releases every handler recorded against ownerInstance and returns the action that gives them back (#562). PluginManager calls this for a loaded copy of a module just before a newer copy of the same module builds its container and runs registerSelf(): from then on the older copy receives no event, so nothing the newer copy publishes while it loads reaches code of the copy it replaces. When the newer copy fails to load, the framework first releases what the failed copy registered and then runs the returned action, which puts each released handler back at its place in its event type's list, so it is dispatched as before and a Subscription the older copy holds still removes it; when the newer copy loads, the action is dropped and the older copy is unloaded. Running the action more than once restores nothing more. A handler recorded against another copy is never released or restored here: only entries recorded against ownerInstance are matched, whichever copy's code registered them. Intended for PluginManager, not for module authors.
      Parameters:
      ownerInstance - the loaded copy being superseded; null releases nothing
      Returns:
      the action that restores what this call released
      Since:
      6.3.0
    • restore

      private void restore(List<EventBus.ReleasedHandler> released)
    • beginRegistrationScope

      public void beginRegistrationScope(UltiToolsPlugin owner)
      Attributes every handler registered on this thread, until endRegistrationScope(), to owner when the registration names no owner instance itself (#506). The framework opens this scope while it loads a module -- around the module's container refresh, where @PostConstruct runs, and around its registerSelf() -- so that a module's programmatic subscriptions made while it loads are released with that module instance. Intended for PluginManager, not for module authors. Scopes do not nest.
      Parameters:
      owner - the module instance being loaded
      Since:
      6.3.0
    • endRegistrationScope

      public void endRegistrationScope()
      Ends the scope started by beginRegistrationScope(UltiToolsPlugin) on this thread.
      Since:
      6.3.0
    • ownerInstanceOrScope

      private UltiToolsPlugin ownerInstanceOrScope(UltiToolsPlugin ownerInstance, String ownerModule)
      The module instance a registration is recorded against: the one it names; otherwise the module the framework is loading on this thread; otherwise the copy listed as loaded under ownerModule (#562 item 1); otherwise none.
    • publish

      public void publish(ModuleEvent event)
      Publish an event synchronously. Handlers run on the calling thread in priority order.
    • publishAsync

      public void publishAsync(ModuleEvent event)
      Publish an event asynchronously. Handlers run on a worker thread. Cancellable events are rejected — cancellation is only meaningful for sync dispatch.
    • shutdown

      public void shutdown()
      Shutdown the async thread pool. Called on plugin disable.
    • collectHandlers

      private List<HandlerEntry> collectHandlers(Class<? extends ModuleEvent> eventType)
      Collect all handlers matching the event type (including superclass handlers), sorted by priority.
    • invokeHandler

      private void invokeHandler(HandlerEntry entry, ModuleEvent event)