Class WidgetsMixin

java.lang.Object
org.apache.juneau.console.widgets.WidgetsMixin

public class WidgetsMixin extends Object
The widget toolkit's serving-path mixin: the mount, asset-URL API and serving endpoints for the widget-owned browser runtime (juneau-calendar.js, juneau-calendar.css), plus the contract-version handshake constants those runtimes bake in.

Compose into a host resource via @Rest(mixins=WidgetsMixin.class); the asset URLs then become available alongside the host's own endpoints.

These assets still need the view runtime beside them

The bytes live here, but they are not a standalone widget runtime: the calendar script resolves its glyphs through the rich-view module's icon registry (juneau-icons.js) and pushes its popovers onto the ONE shared layer stack that juneau-views.js publishes. A page that loads this script must therefore also load the view module's juneau-icons.js and juneau-views.js. "Widgets without views" is deliberately not a goal here; what this module owns is the bean contracts and the bytes, not independence from views.

For backwards compatibility the rich-view mixin keeps deprecated accessors at the same paths it served these assets from before they moved, reading the bytes from this module's classpath. An existing application therefore keeps working unchanged; a new one composes this mixin.

Contract-version handshake:

Each *_CONTRACT_VERSION constant is the handshake stamp the matching runtime bakes in. CALENDAR_CONTRACT_VERSION aliases CalendarDef.CONTRACT_VERSION; BAR_CONTRACT_VERSION aliases BarSlot.CONTRACT_VERSION; HEADER_CONTRACT_VERSION is a literal (the header bean is gone). The three are deliberately distinct from one another: a calendar-envelope revision must never force a header or bar-sidecar bump, or vice-versa.

Cache-busting + versioned URLs:

widgetAssetUrl(String) carries the same ?v=<buildVersion>-<hash8> content-sensitive cache-buster shape the views mixin uses: an 8-hex-char content hash of the asset's own served bytes, computed once and cached. Keying the buster off content rather than the version string alone matters for -SNAPSHOT builds, whose version is stable across dev rebuilds. The hashing itself is the shared ChecksumUtils.hash8(byte[]) function reached through ClasspathAssetCache; this module holds its own cache instance anchored on this class, so its buildVersion resolves this module's implementation version rather than a neighbouring module's. The two modules share the hash function, not a cache.

The serving-path Widget.validate() gate

This class also nests WidgetsMixin.WidgetValidationProcessor, a ResponseProcessor that calls Widget.validate() on any REST response content that is a Widget, fail-closed, ahead of every byte-writing processor. It is registered two ways — both belt-and-braces, not redundant duplicates, since ResponseProcessorList de-duplicates by class:

  • Via ServiceLoader (META-INF/services/org.apache.juneau.rest.server.processor.ResponseProcessor), so it applies to every resource on a classpath that carries this module, with no consumer opt-in.
  • Via this class's own @Rest(responseProcessors=...) + mergeResponseProcessorsIntoHost=true, so a host that composes this mixin is covered even if its classpath loses the services file (a shading/repackaging step, for example).
It is declared as a nested class here — rather than a new top-level file — because Widgets_ModuleBoundary_Test.b01_onlyTheMixinReferencesTheRestServingFramework allowlists exactly this file as the module's single exception to "the beans stay independent of the REST serving framework"; a response processor is itself a serving-framework type, so nesting it here keeps that rule literally true rather than requiring an amendment.
See Also:
Since:
10.0.0
  • Field Details

    • CALENDAR_JS_PATH

      public static final String CALENDAR_JS_PATH
      The URL path at which the reusable-calendar runtime is served (relative to the host mount).
      Load order is a contract, not a preference:

      This <script> MUST come after the view module's juneau-views.js. The calendar's "+N more" popover is pushed onto the ONE shared layer stack that script publishes, so Escape, focus return and z-order match every other layer in the page. The calendar deliberately defines no second stack of its own: if the shared one is absent it fails loud rather than opening a popover nothing can dismiss.

      See Also:
    • CALENDAR_CSS_PATH

      public static final String CALENDAR_CSS_PATH
      The URL path at which the reusable-calendar stylesheet is served (relative to the host mount).
      See Also:
    • CALENDAR_CONTRACT_VERSION

      public static final String CALENDAR_CONTRACT_VERSION
      The per-month calendar-event envelope contract-version handshake constant that the calendar runtime bakes in, aliased from the value the calendar model emits (CalendarDef.CONTRACT_VERSION).
      See Also:
    • HEADER_CONTRACT_VERSION

      public static final String HEADER_CONTRACT_VERSION
      The app-header refresh-envelope contract-version handshake constant that the console shell bakes in.
      See Also:
    • BAR_CONTRACT_VERSION

      public static final String BAR_CONTRACT_VERSION
      The bar-slot refresh-envelope contract-version handshake constant that the console shell bakes in, aliased from the value the bar model emits (BarSlot.CONTRACT_VERSION).
      See Also:
  • Constructor Details

  • Method Details

    • getCalendarScript

      [GET /juneau-calendar.js] — serve the reusable-calendar runtime.
      Returns:
      The calendar runtime as a JavaScript HttpResource.
    • getCalendarStylesheet

      [GET /juneau-calendar.css] — serve the reusable-calendar stylesheet.
      Returns:
      The calendar stylesheet as a CSS HttpResource.
    • widgetAssetUrl

      public static String widgetAssetUrl(String path)
      Returns the servlet-relative URL for a widget asset served by this mixin, carrying a ?v=<buildVersion>-<hash8> content-sensitive cache-buster suitable for a page's head= block.
      Parameters:
      path - One of the asset path constants (CALENDAR_JS_PATH, CALENDAR_CSS_PATH).
      Returns:
      The servlet-relative asset URL with the version+content-hash cache-buster appended.
      Throws:
      IllegalArgumentException - If this mixin does not ship the bytes for the given path.
    • widgetAssetUrl

      public static String widgetAssetUrl(RestRequest req, String path)
      Returns a real, browser-fetchable absolute URL for a widget asset served by this mixin, resolved against the given request's context path and mount — carrying the same cache-buster as widgetAssetUrl(String).

      widgetAssetUrl(String) returns a servlet:-prefixed URL that only Juneau's own HTML serializer resolves. A template-rendering consumer sits downstream of that serializer, so it never sees the rewrite and would otherwise receive the literal, unfetchable string. This overload resolves the URL itself, per-request.

      The path is validated before the request is touched, so an unserved path is rejected identically with or without a live request.

      Parameters:
      req - The current request, supplying the context path/mount to resolve against.
      path - One of the asset path constants (CALENDAR_JS_PATH, CALENDAR_CSS_PATH).
      Returns:
      The absolute asset URL with the version+content-hash cache-buster appended.
      Throws:
      IllegalArgumentException - If this mixin does not ship the bytes for the given path.