Class ViewsMixin

java.lang.Object
org.apache.juneau.console.views.ViewsMixin

public class ViewsMixin extends Object
Mixin that serves the first-party rich-view runtime assets — juneau-views.js, juneau-ribbon.js, juneau-renders.js, juneau-views.css, the opt-in juneau-regions.js region-populate runtime, the opt-in juneau-config.js/juneau-config.css column-chooser runtime — each at its stable path, plus deprecated compatibility mounts for the two assets that have since moved to the widget module.

Compose into a host resource via @Rest(mixins=ViewsMixin.class); the asset URLs then become available alongside the host's own endpoints, so browser pages can load the runtime without the application hosting it itself. This mirrors the sibling DataTablesMixin/ConsoleChromeMixin serving pattern (those modules are not dependencies of this one, so they are not linked here).

What this ships (and what it deliberately does not):

Juneau's jars don't copy the DataTables library or jQuery. Only the thin, first-party runtime is served here; the DataTables, jQuery and Buttons files come from the WebJars that juneau-console-datatables declares, served by WebJarsMixin. The base juneau-views.css .tag chip is dependency-free (neutral, no colors); console-ui's chrome.css themes the same .tag.<domain>.<value> classes when present, but this module takes no dependency on it.

Relocated: two assets now ship in the widget module

juneau-calendar.js and juneau-calendar.css are widget runtimes, not table runtimes, and their bytes now live in juneau-console-widgets beside the bean contracts that drive them. WidgetsMixin is where a new application gets them.

This mixin keeps a deprecated mount and path constant for each of the two so that an existing @Rest(mixins=ViewsMixin.class) application keeps working with no change: the mount reads the widget module's bytes off the classpath (that module is a compile-scope dependency of this one) rather than holding a second copy, so the body and the cache-buster are identical to what WidgetsMixin serves. Composing both mixins is therefore harmless.

The relocation does not make that script standalone: it still resolves glyphs through this module's juneau-icons.js and pushes its popovers onto the ONE shared layer stack juneau-views.js publishes. A page loading the widget calendar runtime must still load this module's juneau-icons.js and juneau-views.js first.

Cache-busting + versioned URLs:

Each asset is served with a one-day Cache-Control and referenced from a page's head= block with a ?v=<buildVersion>-<hash8> cache-buster (see viewAssetUrl(String), or viewAssetUrl(RestRequest, String) for a template-rendered consumer that needs the URL already resolved to an absolute, browser-fetchable form), where hash8 is an 8-hex-char CRC32 of that asset's own served bytes, computed once and cached (classpath resources never change within a running JVM). Keying the buster off content rather than buildVersion alone matters for -SNAPSHOT builds: that version string is stable across dev rebuilds, so a version-only buster would keep serving a browser's stale cached copy after every rebuild - the content hash changes the instant the bytes do, with no SNAPSHOT special-casing needed. buildVersion is the framework's implementation version, falling back to "dev" when running from an unpackaged (IDE/test) classpath. The served endpoint ignores the query string, so any (or no) ?v= still resolves to the same asset.

Contract-version handshake:

CONTRACT_VERSION is the single wire-contract discriminator for a VIEW_META sidecar. juneau-views.js bakes in the same value so the client can fail loud when a served sidecar's contractVersion differs from the runtime's.

Mixin-only deployment:

The mount paths are pinned at the op level by @RestGet(path=...) on the serving methods; a class-level @Rest(paths=...) would be silently ignored under the mixin pattern.

See Also:
Since:
10.0.0
  • Field Details

    • VIEWS_JS_PATH

      public static final String VIEWS_JS_PATH
      The URL path at which the client initializer is served (relative to the host mount). A page with any datatables card must load juneau-datatables.js (DATATABLES_JS_PATH) before this script, so window.JuneauDataTables is already present when buildOptions wires up that card's ajax. This mixin does not serve juneau-datatables.js itself — the resource mixes in DataTablesMixin for that, the same way it already mixes in ViewsMixin for this script; a duplicate @RestGet for the same path on two mixed-in classes would fail route registration. A missing window.JuneauDataTables when a server-side table initializes fails loudly (console warning, no silent GET fallback) rather than silently misbehaving. A page with any ribbon options should likewise load juneau-ribbon.js before this script, so window.JuneauViews.ribbon is present when buildOptions merges that view's active ribbon state into the request; unlike the JuneauDataTables case this one degrades rather than fails — a missing window.JuneauViews.ribbon warns and simply contributes no ribbon filters, since a view with no ribbon configured never needed juneau-ribbon.js loaded at all.
      See Also:
    • DATATABLES_JS_PATH

      public static final String DATATABLES_JS_PATH
      The URL path of the DataTables glue script, juneau-datatables.js (the same path as DataTablesMixin.GLUE_PATH).

      Named here so viewAssetUrl(RestRequest, String) can build its cache-busted URL, and so the console's "datatables-glue" toolkit pack can name the path without importing the datatables package (juneau-console-freemarker forbids that import; see its ModuleGraph_ImportScan_Test). This mixin does not serve it (see VIEWS_JS_PATH for why); DataTablesMixin does. On a console page the "datatables-glue" toolkit pack emits it for every type="datatables" card, client or server mode, after jQuery and DataTables and before juneau-views.js. A host with datatables cards composes DataTablesMixin and WebJarsMixin.

      Example:

      @Rest(mixins={ViewsMixin.class, DataTablesMixin.class, WebJarsMixin.class}) public class MyResource extends BasicRestServlet { // Emitted by the "datatables-glue" pack before juneau-views.js: // ViewsMixin.viewAssetUrl(req, ViewsMixin.DATATABLES_JS_PATH) }

      See Also:
    • RIBBON_JS_PATH

      public static final String RIBBON_JS_PATH
      The URL path at which the ribbon runtime is served (relative to the host mount).
      See Also:
    • RENDERS_JS_PATH

      public static final String RENDERS_JS_PATH
      The URL path at which the renderer registry is served (relative to the host mount).
      See Also:
    • VIEWS_CSS_PATH

      public static final String VIEWS_CSS_PATH
      The URL path at which the base view stylesheet is served (relative to the host mount).
      See Also:
    • ICONS_JS_PATH

      public static final String ICONS_JS_PATH
      The URL path at which the icon registry is served (relative to the host mount).
      Example:

      // Page-level sprite layers, read once before the chrome draws: // <script src="/views/juneau-icons.js" // data-juneau-icon-replacement="/my/set.svg" // data-juneau-icon-override="/my/overrides.svg"></script>

      See Also:
    • SEARCH_JS_PATH

      public static final String SEARCH_JS_PATH
      The URL path at which the column-search engine is served (relative to the host mount). This dependency-free <script> loads before juneau-views.js (like the icon registry): it publishes JuneauViews.search — the client mirror of the server-side SearchExpressionParser/ SearchOperatorSet/InMemoryBeanQueryContext context that the header search popup and a client-mode grid use to parse and evaluate each column's raw search expression.
      See Also:
    • PAGESTATE_JS_PATH

      public static final String PAGESTATE_JS_PATH
      The URL path at which the general page-state store is served (relative to the host mount). This dependency-free <script> loads before juneau-views.js and juneau-config.js (like the icon registry and column-search engine): it publishes JuneauViews.pageState — a per-table / per-page key/value store, backed by localStorage by default and degrading to a silent no-op when browser storage is blocked. The datatable View Settings dialog and any other page preference share it.
      See Also:
    • URLSTATE_JS_PATH

      public static final String URLSTATE_JS_PATH
      The URL path at which the shareable "Copy link" URL-state codec is served (relative to the host mount). This dependency-free <script> loads before juneau-views.js and juneau-config.js (like the icon registry, column-search engine, and page-state store): it publishes JuneauViews.urlState — the single codec for the one ?state= query parameter that carries a shareable link's live tab, primary- table filters, and primary-table sort (never the browser-local View Settings, and never nested tables).
      See Also:
    • BUS_JS_PATH

      public static final String BUS_JS_PATH
      The URL path at which the in-page message bus is served (relative to the host mount). This dependency-free <script> publishes JuneauViews.bus — topic declare/claim, publish/subscribe with optional retention, and the frame and source bridges — and it must load before juneau-views.js, juneau-regions.js and juneau-console.js, all of which read it. The "views" toolkit pack lists it first. A page that wires topics without it fails loud with E-JS-46.
      Example:

      // A hand-written page head that does not use the "views" toolkit pack: the bus goes first. var bus = ViewsMixin.viewAssetUrl(req, ViewsMixin.BUS_JS_PATH); var views = ViewsMixin.viewAssetUrl(req, ViewsMixin.VIEWS_JS_PATH); // <script src="${bus}"></script><script src="${views}"></script>

      See Also:
    • SYMBOLS_SVG_PATH

      public static final String SYMBOLS_SVG_PATH
      The URL path at which the shared SVG symbol sprite is served (relative to the host mount). juneau-icons.js fetches this next to itself by default (pack original); the key/legend file is not served to browsers. An app replaces part or all of this shipped set per page with a replacement and/or override sprite that uses the same juneau-sym-{stem} symbol ids.
      Example:

      // Page-level sprite layers, read once before the chrome draws: // <script src="/views/juneau-icons.js" // data-juneau-icon-replacement="/my/set.svg" // data-juneau-icon-override="/my/overrides.svg"></script>

      See Also:
    • SYMBOLS_MATERIAL_SVG_PATH

      public static final String SYMBOLS_MATERIAL_SVG_PATH
      The URL path at which the opt-in Material Symbols Outlined sprite is served (relative to the host mount). Selected as the legacy replacement layer by JuneauViews.icons.pack("material") / data-juneau-icon-pack="material"; new apps point data-juneau-icon-replacement / JuneauViews.icons.sprites({replacementUrl}) at the set they want instead. Default remains SYMBOLS_SVG_PATH (Juneau's own shipped set). The Material pack loads as the replacement layer on top of that shipped sprite, so stems the Material file does not carry fall back to the shipped glyph.
      Example:

      // Opt in to the Material Symbols sprite as the replacement layer over the shipped set, before the chrome draws: // <script src="/views/juneau-icons.js" data-juneau-icon-pack="material"></script> // or, from script before first paint: // JuneauViews.icons.pack("material");

      See Also:
    • REGIONS_JS_PATH

      public static final String REGIONS_JS_PATH
      The URL path at which the opt-in region-populate runtime is served (relative to the host mount). A page with no data-juneau-region element never needs to load it.
      Load order is a contract, not a preference:

      This <script> MUST come after juneau-views.js. The region runtime publishes onto the same window.JuneauViews namespace that juneau-views.js creates, and reuses that runtime's renderAsyncStatus status renderer rather than defining one of its own.

      See Also:
    • HELPERS_JS_PATH

      public static final String HELPERS_JS_PATH
      The URL path at which the opt-in region-populate paint library is served (relative to the host mount). A page of purely custom regions (every populate hand-writes its own DOM) never needs to load it.
      Load order is a contract, not a preference:

      This <script> MUST come after juneau-regions.js (itself after juneau-views.js). fieldGrid's renderer dispatch reads the renderer registry juneau-views.js publishes and its markdown/sanitized-HTML paths reuse that runtime's allowlist copiers, and ctx.helpers (a bare pass-through of this asset's exports) is a field of the ctx juneau-regions.js freezes.

      See Also:
    • DATA_JS_PATH

      public static final String DATA_JS_PATH
      [GET] path of the DataRegistry runtime (JuneauViews.data): the frames behind data: bus topics. Loaded after BUS_JS_PATH; the "data" toolkit pack serves it.
      See Also:
    • RUN_VIEW_JS_PATH

      public static final String RUN_VIEW_JS_PATH
      The URL path at which the opt-in terminal-view module is served (relative to the host mount).
      Load order is a contract, not a preference:

      This <script> MUST come after juneau-regions.js (itself after juneau-views.js) and before juneau-helpers.js. It registers its populator with juneau-regions.js at load time; icons are built through JuneauViews.helpers.icon, which is resolved at call time, so loading before juneau-helpers.js is safe.

      Since:
      10.0.0
      See Also:
    • CONFIG_JS_PATH

      public static final String CONFIG_JS_PATH
      The URL path at which the opt-in column-chooser runtime is served (relative to the host mount). A consumer adds this <script> after juneau-views.js; a non-configurable table never loads it.
      See Also:
    • CONFIG_CSS_PATH

      public static final String CONFIG_CSS_PATH
      The URL path at which the opt-in column-chooser stylesheet is served (relative to the host mount).
      See Also:
    • CALENDAR_JS_PATH

      @Deprecated(since="10.0.0", forRemoval=false) public static final String CALENDAR_JS_PATH
      Deprecated.
      The calendar runtime now ships in the widget module; compose WidgetsMixin and use its constant of the same name. This one remains only so that an application composing this mixin alone keeps serving the asset at the same URL.
      The URL path at which the opt-in reusable-calendar runtime is served (relative to the host mount). A page with no calendar never loads it.
      Load order is a contract, not a preference:

      This <script> MUST come after juneau-views.js. The calendar's "+N more" popover is pushed onto the ONE shared layer stack that juneau-views.js publishes, so that Escape, focus return and z-order are the same as 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 (console error plus a visible in-cell refusal) rather than quietly opening a popover nothing can dismiss.

      See Also:
    • CALENDAR_CSS_PATH

      @Deprecated(since="10.0.0", forRemoval=false) public static final String CALENDAR_CSS_PATH
      Deprecated.
      The calendar stylesheet now ships in the widget module; compose WidgetsMixin and use its constant of the same name. This one remains only so that an application composing this mixin alone keeps serving the asset at the same URL.
      The URL path at which the opt-in reusable-calendar stylesheet is served (relative to the host mount).
      See Also:
    • CONSOLE_JS_PATH

      public static final String CONSOLE_JS_PATH
      The URL path at which the console shell runtime is served (relative to the host mount).

      juneau-console.js mounts the C1 page contract (header, nav, cards, footer) from a page's #juneau-page script island. This module takes a compile-scope dependency on juneau-console so that a views-only application can serve the console shell from the same mixin it already composes, without separately adding ConsoleChromeMixin. The toolkit pack (juneau-views.js and siblings) deliberately does not bundle this script: a console page's shell loads it once via PageCapture.writeBody, and a second copy from the toolkit pack would double-load the runtime.

      Example:

      // A views-only application serves the console shell at the same stable (unprefixed) path ConsoleChromeMixin serves it at. @Rest(mixins=ViewsMixin.class) public class MyResource {} // GET /juneau-console.js now returns the shell runtime.

      See Also:
    • CONTRACT_VERSION

      public static final String CONTRACT_VERSION
      The frozen VIEW_META contract-version handshake constant. FTL <@card type="datatables"> catalogs emit this on the lifted view object.

      Templates never author view.contractVersion: the framework stamps this value when it lifts the catalog, so a contract bump never touches adopter templates. A pre-built envelope body is rejected at render time, and ConsoleTemplateValidator's view-contract-version rule flags a literal pin statically.

      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. Deliberately distinct from CONTRACT_VERSION and BAR_CONTRACT_VERSION: a header-envelope revision must never force a view-sidecar or bar-sidecar bump, or vice-versa.
      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. Deliberately a distinct constant from HEADER_CONTRACT_VERSION (see that constant).
      See Also:
    • SLOT_CONTRACT_VERSION

      public static final String SLOT_CONTRACT_VERSION
      The slot-envelope (SLOT_META) contract-version handshake constant that juneau-views.js bakes in. Deliberately a distinct constant from CONTRACT_VERSION (the inner VIEW_META object): a slot-envelope revision must never force a view-sidecar bump, or vice-versa.
      See Also:
  • Constructor Details

  • Method Details