Skip to content

JWebMP/Client

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

55 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

JWebMP Client

Build Maven Central Maven Snapshot License

Java 25+ Guice 7 Vert.X 5 Maven 4

Client SPI library for JWebMP β€” defines the contracts, AJAX pipeline types, HTML component interfaces, call interceptor SPIs, and component model that all JWebMP modules program against without pulling in the full core runtime.

Provides the AjaxCall/AjaxResponse pipeline, IPage/IPageConfigurator page contracts, the SiteCallIntercepter interception chain, and the component-model interface hierarchy (IComponentHierarchyBase, IComponentHTMLBase, etc.) that higher-level modules (core, vertx, plugins) build on top of. Extension is SPI-driven via ServiceLoader.

Every interface defined here serves dual purposes:

  • Compile-time contracts β€” higher-level modules code against the interfaces in this library, enabling strict type safety across the ecosystem without circular dependencies
  • Runtime SPI discovery β€” implementations are discovered via ServiceLoader (provides…with in JPMS or META-INF/services), keeping the module graph clean and extensible

Built on GuicedEE Client Β· JWebMP Β· JPMS module com.jwebmp.client Β· Java 25+

πŸ“¦ Installation

<dependency>
  <groupId>com.jwebmp</groupId>
  <artifactId>jwebmp-client</artifactId>
</dependency>
Gradle (Kotlin DSL)
implementation("com.jwebmp:jwebmp-client:2.0.0-SNAPSHOT")

Version is managed by the JWebMP BOM.

✨ Features

  • AJAX pipeline DTOs β€” AjaxCall and AjaxResponse are CallScope-scoped, JSON-serializable objects that carry request payloads and DOM update instructions between browser and server
  • Three interceptor SPIs β€” SiteCallIntercepter, AjaxCallIntercepter, DataCallIntercepter β€” each uses CRTP and IDefaultService for sort-ordered, pluggable request processing
  • Page contracts β€” IPage, IPageConfigurator, IBody, IHead, IHtml define the full page lifecycle without depending on core rendering
  • Component model interfaces β€” IComponentHierarchyBase, IComponentHTMLBase, IComponentHTMLAttributeBase, IComponentStyleBase, IComponentFeatureBase, IComponentEventBase, IComponentDataBindingBase, IComponentDependencyBase, IComponentThemeBase, IComponentHTMLOptionsBase, and IComponentBase form the type-safe component tree
  • Databind hooks β€” IOnDataBind, IOnDataBindCloak, IOnComponentAdded, IOnComponentHtmlRender, IOnComponentConfigured, IAfterRenderComplete, and IClientVariableWatcher fire at specific points in the render lifecycle
  • Render-ordering SPIs β€” RenderBeforeLinks, RenderAfterLinks, RenderBeforeScripts, RenderAfterScripts, RenderBeforeDynamicScripts, RenderAfterDynamicScripts β€” fine-grained control over asset insertion order
  • User-agent detection β€” UADetector parser bound as a Guice singleton for browser/device detection (Browsers, BrowserGroups, CSSVersions, HTMLVersions)
  • Plugin metadata annotations β€” @ComponentInformation, @PluginInformation, @FeatureInformation, @PageConfiguration for discovery and documentation
  • Jackson integration β€” JavaScriptPart base class provides JSON serialization for all component options via IJsonRepresentation
  • CSS/JS reference types β€” CSSReference and JavascriptReference model external stylesheets and scripts with version metadata
  • HTML child-constraint interfaces β€” GlobalChildren, GlobalFeatures, HTMLFeatures, FormChildren, and marker interfaces enforce parent/child relationships at compile time
  • Generics toolkit β€” WebReference, Pair, XYObject, FileTemplates, CompassPoints, Direction, Positions, and more β€” reusable typed data structures
  • Exception hierarchy β€” InvalidRequestException, MissingComponentException, NullComponentException, NoServletFoundException, UserSecurityException β€” typed error semantics for the request pipeline
  • Script provider SPI β€” ScriptProvider allows dynamic script components to be contributed to any page
  • Static strings β€” StaticStrings centralises well-known constants used across the framework

πŸš€ Quick Start

Register a page configurator via JPMS ServiceLoader

module my.app {
    requires com.jwebmp.client;

    provides com.jwebmp.core.services.IPageConfigurator
        with my.app.MyPageConfigurator;
}

Implement the configurator β€” it runs before each page render

public class MyPageConfigurator
        implements IPageConfigurator<MyPageConfigurator> {

    @Override
    public IPage<?> configure(IPage<?> page) {
        // add CSS/JS references, configure body children, etc.
        return page;
    }

    @Override
    public Integer sortOrder() {
        return 100;  // higher = later
    }
}

Intercept AJAX calls

public class AuditInterceptor
        implements AjaxCallIntercepter<AuditInterceptor> {

    @Override
    public void intercept(AjaxCall<?> call, AjaxResponse<?> response) {
        log.info("AJAX event: {}", call.getEventType());
    }

    @Override
    public Integer sortOrder() {
        return 10;
    }
}

Provide a dynamic script

public class InlineScript implements ScriptProvider {
    @Override
    public IComponentHierarchyBase<?, ?> produceScript() {
        // return a component that renders as a <script> block
    }
}

πŸ“ AJAX Pipeline Flow

Browser event
 └─ JSON payload β†’ AjaxCall (deserialized, CallScope-scoped)
     └─ SiteCallIntercepter chain (sorted by sortOrder)
         └─ AjaxCallIntercepter chain (AJAX events only)
         └─ DataCallIntercepter chain (startup data calls only)
             └─ Event handler processes call
                 └─ AjaxResponse built (component updates, reactions, scripts)
                     └─ JSON response β†’ Browser applies DOM updates

πŸ”Œ SPI Extension Points

All SPIs are discovered via ServiceLoader. Register implementations with JPMS provides...with or META-INF/services.

SiteCallIntercepter

Intercepts every site call (first page load). Local storage, session storage, and other client-side items are not yet available:

public class MySecurityInterceptor
        implements SiteCallIntercepter<MySecurityInterceptor> {

    @Override
    public void intercept(AjaxCall<?> call, AjaxResponse<?> response) {
        // validate session, check IP, etc.
    }

    @Override
    public Integer sortOrder() {
        return 10;  // run early
    }
}

AjaxCallIntercepter

Intercepts AJAX event calls β€” extends SiteCallIntercepter so the same intercept() method applies:

public class AuditInterceptor
        implements AjaxCallIntercepter<AuditInterceptor> {

    @Override
    public void intercept(AjaxCall<?> call, AjaxResponse<?> response) {
        log.info("AJAX event: {}", call.getEventType());
    }
}

DataCallIntercepter

Intercepts startup data calls β€” fires immediately after page delivery:

public class InitDataInterceptor
        implements DataCallIntercepter<InitDataInterceptor> {

    @Override
    public void intercept(AjaxCall<?> call, AjaxResponse<?> response) {
        // load initial data into the response
    }
}

IPageConfigurator

Configures pages before rendering. Implements IDefaultService (sort-ordered) and IServiceEnablement (can be toggled on/off):

public class AnalyticsConfigurator
        implements IPageConfigurator<AnalyticsConfigurator> {

    @Override
    public IPage<?> configure(IPage<?> page) {
        page.addJavaScriptReference(analyticsScript);
        return page;
    }
}

ScriptProvider

Provides dynamic script components to the page:

public class InlineScript implements ScriptProvider {
    @Override
    public IComponentHierarchyBase<?, ?> produceScript() {
        // return a component that renders as a <script> block
    }
}

Render-ordering SPIs

SPI Purpose
RenderBeforeLinks Insert content before CSS <link> tags
RenderAfterLinks Insert content after CSS <link> tags
RenderBeforeScripts Insert content before <script> tags
RenderAfterScripts Insert content after <script> tags
RenderBeforeDynamicScripts Insert content before dynamic/inline scripts
RenderAfterDynamicScripts Insert content after dynamic/inline scripts

Databind / Lifecycle SPIs

SPI Purpose
IOnDataBind Fires when a component's data-bind is processed
IOnDataBindCloak Fires for cloaked data-bind components
IOnComponentAdded Fires when a child is added to a component
IOnComponentConfigured Fires after component configuration completes
IOnComponentHtmlRender Fires during component HTML rendering
IAfterRenderComplete Fires after full render completes
IClientVariableWatcher Monitors client-side variable changes

🧱 Component Model Interface Hierarchy

The client defines the full interface chain that core implements with concrete classes:

IComponentBase                   β†’ ID, name, properties, JSON serialization
 └─ IComponentHierarchyBase     β†’ parent/child tree, CSS/JS references
     └─ IComponentHTMLBase      β†’ tag rendering, text, raw HTML
         └─ IComponentHTMLAttributeBase β†’ HTML attributes (typed enums)
             └─ IComponentHTMLOptionsBase β†’ JavaScript options (JavaScriptPart)
                 └─ IComponentStyleBase     β†’ inline CSS via the CSS builder
                     └─ IComponentThemeBase     β†’ theme support
                         └─ IComponentDataBindingBase β†’ data-bind hooks
                             └─ IComponentDependencyBase  β†’ CSS/JS dependency refs
                                 └─ IComponentFeatureBase    β†’ Feature attachment
                                     └─ IComponentEventBase     β†’ Event attachment

These interfaces use CRTP generics so that concrete implementations in core expose fluent APIs without unchecked casts.

πŸ—ΊοΈ Module Graph

com.jwebmp.client
 β”œβ”€β”€ com.guicedee.client              (DI, lifecycle, CallScope)
 β”œβ”€β”€ com.guicedee.jsonrepresentation  (JSON serialization β€” IJsonRepresentation)
 β”œβ”€β”€ jakarta.activation
 β”œβ”€β”€ org.apache.commons.io
 β”œβ”€β”€ io.smallrye.mutiny               (reactive types)
 β”œβ”€β”€ net.sf.uadetector.core           (user-agent parsing)
 └── net.sf.uadetector.resources

🧩 JPMS

Module name: com.jwebmp.client

The module:

  • exports com.jwebmp.core.base.ajax, com.jwebmp.core.base.client, com.jwebmp.core.base.html.attributes, com.jwebmp.core.base.html.interfaces, com.jwebmp.core.base.html.interfaces.children, com.jwebmp.core.base.html.interfaces.children.generics, com.jwebmp.core.base.html.interfaces.events, com.jwebmp.core.base.interfaces, com.jwebmp.core.base.references, com.jwebmp.core.base.servlets.enumarations, com.jwebmp.core.base.servlets.interfaces, com.jwebmp.core.generics, com.jwebmp.core.htmlbuilder.css.enumarations, com.jwebmp.core.htmlbuilder.css.themes, com.jwebmp.core.htmlbuilder.javascript, com.jwebmp.core.htmlbuilder.javascript.events.interfaces, com.jwebmp.core.services, com.jwebmp.core.annotations, com.jwebmp.core.events.services, com.jwebmp.core.databind, com.jwebmp.interception.services, com.jwebmp.core.plugins, com.jwebmp.core.exceptions
  • provides IGuiceModule with JWebMPClientBinder, IGuiceConfigurator with JWebMPClientConfiguration
  • uses AjaxCallIntercepter, DataCallIntercepter, SiteCallIntercepter
  • opens all exported packages to com.fasterxml.jackson.databind for JSON serialization; com.jwebmp.core.events.services additionally to com.google.guice

πŸ—οΈ Key Classes

Class Role
AjaxCall Incoming AJAX request payload β€” deserialized from JSON, CallScope-scoped
AjaxResponse Outgoing AJAX response β€” carries component updates, reactions, and scripts
AjaxComponentUpdates Describes a single component DOM update (insert type, HTML content)
AjaxResponseReaction Client-side reaction (redirect, dialog, etc.) with ReactionType
AjaxComponentInsertType Enum β€” where to insert a component update (replace, append, prepend, etc.)
HeadersDTO Typed wrapper for HTTP headers passed through the AJAX pipeline
JavaScriptPart Base class for all JSON-serializable component options (via com.guicedee.jsonrepresentation)
JWebMPClientBinder IGuiceModule β€” binds AjaxCall/AjaxResponse in CallScope, interceptor sets as singletons, UserAgentStringParser
JWebMPClientConfiguration IGuiceConfigurator β€” enables classpath, annotation, field, and method scanning
JWebMPInterceptionBinder Guice Key constants for the three interceptor sets
CSSReference Models an external CSS stylesheet with version metadata
JavascriptReference Models an external JavaScript file with version metadata
IPage Full page abstraction β€” head, body, browser, document type, CSS/JS references
IPageConfigurator SPI β€” configure a page before rendering
IBody / IHead / IHtml Page-section contracts
SiteCallIntercepter SPI β€” intercept site-level calls
AjaxCallIntercepter SPI β€” intercept AJAX event calls (extends SiteCallIntercepter)
DataCallIntercepter SPI β€” intercept startup data calls (extends SiteCallIntercepter)
ScriptProvider SPI β€” provide dynamic script components
PageConfiguration Annotation β€” maps a page to a URL path
ComponentInformation Annotation β€” metadata for component discovery/docs
PluginInformation Annotation β€” metadata for plugin discovery/docs
FeatureInformation Annotation β€” metadata for feature discovery/docs
FileTemplates Utility for managing and rendering file templates
WebReference Base class for CSSReference and JavascriptReference
StaticStrings Centralised well-known string constants

HTML Interface Types

Interface Purpose
GlobalChildren Marker for elements that accept any flow/phrasing content
GlobalFeatures Marker for global HTML features
HTMLFeatures Marker for HTML-specific features
FormChildren Marker for elements valid inside <form>
NoClosingTag Marker for void elements (<br>, <img>, etc.)
NoIDTag Marker for elements that should not render an id attribute
NoClassAttribute Marker for elements that should not render a class attribute
DisplayObjectType Enum β€” block, inline, inline-block rendering hint
AttributeDefinitions Enum β€” standard HTML attributes
ContainerType Enum β€” container classification

Client / Browser Types

Class Purpose
Browsers Enum of known browsers
BrowserGroups Enum grouping browsers by engine/vendor
CSSVersions Enum of CSS specification levels
HTMLVersions Enum of HTML specification levels
HttpMethodTypes Enum of HTTP methods (GET, POST, PUT, DELETE, …)
InternetExplorerCompatibilityMode IE-specific compatibility mode settings

Exception Types

Exception Purpose
InvalidRequestException Malformed or invalid AJAX request
MissingComponentException Referenced component not found in the tree
NullComponentException Null component passed where one is required
NoServletFoundException No servlet/handler registered for the request path
UserSecurityException Security violation during request processing

βš™οΈ Configuration

JWebMPClientConfiguration enables the following IGuiceConfig settings at startup:

Setting Value Purpose
classpathScanning true Scan the classpath for SPI implementations
allowPaths true Allow path-based scanning
fieldInfo true Collect field-level metadata
methodInfo true Collect method-level metadata
annotationScanning true Enable annotation discovery
ignoreClassVisibility true Scan non-public classes
ignoreFieldVisibility true Scan non-public fields
ignoreMethodVisibility true Scan non-public methods

πŸ§ͺ Build & Test

# Build
mvn -B -ntp -DskipTests package

# Test
mvn -B -ntp verify

Prerequisites: Java 25+, Maven 3.9+

🀝 Contributing

Issues and pull requests are welcome β€” please add tests for new SPI implementations or interceptors.

πŸ“„ License

Apache 2.0

About

A client library for interacting with JWebMP without swallowing the entire core

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

Packages

 
 
 

Contributors

Languages