SkillAgentSearch skills...

Core

JWebMP is a Java Web UI Framework for the rapid development of data bound web applications. It allows single language, bi-directional databinding and many more features

Install / Use

/learn @JWebMP/Core

README

JWebMP Core

Build Maven Central Maven Snapshot License

Java 25+ Guice 7 Vert.X 5 Maven 4

Strongly-typed HTML/CSS/JS component model for Java — the heart of JWebMP.

The core defines the HTML language in Java — every HTML element, CSS property, event, and feature is a first-class Java object using CRTP generics. It generates the HTML, JavaScript, and CSS required for any page, and provides the SPI contracts that allow a mass ecosystem of plugins to be created that adhere to the component model.

Every component serves dual purposes:

  • toString(true) renders the component as HTML (with all queued CSS/JS) — use this for server-side rendering, template generation, or serving pages on the Vert.x router
  • toString() renders the component as JSON — use this for AJAX responses, API payloads, or any scenario where the component tree needs to be serialized

Pages can optionally be annotated with @PageConfiguration and served directly via the Vert.x HTTP server, or components can be used standalone to generate HTML/JSON without a server at all.

Provides Page, the full HTML element library (Div, Span, Table, Form, …), a typed CSS builder, 50+ server-driven event adapters, page configurators that inject scripts/styles before render, and a Jackson-serialized AJAX pipeline for live DOM updates. Extension is SPI-driven via ServiceLoader.

Built on JWebMP Client · GuicedEE · Vert.x 5 · JPMS module com.jwebmp.core · Java 25+

📦 Installation

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

Version is managed by the JWebMP BOM.

✨ Features

  • HTML language in Java — the core defines the entire HTML5 element set as typed Java classes, along with CSS and JavaScript rendering rules, forming the foundation that all JWebMP plugins build on top of
  • Dual rendering modestoString(true) produces full HTML with all CSS/JS assets; toString() produces JSON for AJAX/API consumption — same component tree, two output formats
  • Complete HTML element library — every HTML5 element (Div, Span, Table, Form, Input, Select, Canvas, Video, Article, Section, …) is a typed Java class with CRTP fluent API; child constraints are enforced at compile time
  • Typed input elementsInputTextType, InputEmailType, InputNumberType, InputDateType, InputFileType, InputCheckBoxType, InputRadioType, and 15 more — each with the correct HTML attributes
  • Typed CSS builder — annotation-driven CSS properties (@CSS) across 14 sub-packages: backgrounds, borders, colours, fonts, margins, padding, displays, lists, tables, text, outline, measurement, height/width, image — rendered inline or composed via CSSPropertiesFactory
  • 50+ server-driven event adaptersOnClickAdapter, OnChangeAdapter, OnSubmitAdapter, OnDragAdapter, OnKeyDownAdapter, OnMouseEnterAdapter, and many more — each backed by a ServiceLoader SPI (IOnClickService, IOnChangeService, etc.). Events must be their own named classes — anonymous inner classes and lambdas are not supported because the framework relies on class identity for serialization and ServiceLoader discovery
  • Page configurators (optional)IPageConfigurator SPI is an optional hook that modifies pages before rendering — use it to inject CSS links, JavaScript references, dynamic scripts, or top-shelf scripts in priority order; pages work perfectly fine without any configurators
  • Render-ordering hooksRenderBeforeLinks, RenderAfterLinks, RenderBeforeScripts, RenderAfterScripts, RenderBeforeDynamicScripts, RenderAfterDynamicScripts — fine-grained control over asset insertion
  • AJAX pipelineAjaxCall/AjaxResponse (from jwebmp-client) carry event payloads and DOM update instructions; Event base class wires server handlers to browser events
  • Feature systemFeature<O, J> wraps a JavaScript library with typed options (JavaScriptPart), CSS/JS references, and automatic dependency ordering. Features must be their own named classes — the framework uses class identity for deduplication, dependency ordering, and Jackson serialization
  • CSSComponent — render-only CSS classes (no HTML tag) for reusable style-only components
  • DataAdapter — bridges server-side data into raw JSON for component consumption
  • Content Security PolicyContentSecurityPolicy builder for CSP headers
  • Jackson moduleJWebMPJacksonModule registers custom event deserializers at pre-startup
  • Component hierarchy — 11-layer deep CRTP chain: ComponentBaseComponentHierarchyBaseComponentHTMLBaseComponentHTMLAttributeBaseComponentHTMLOptionsBaseComponentStyleBaseComponentThemeBaseComponentDataBindingBaseComponentDependencyBaseComponentFeatureBaseComponentEventBaseComponent → your subclass
  • Utility beltGUIDGenerator, ColourUtils, TextUtilities, EscapeChars, DateUtils, regex patterns (email, date, text)

🚀 Quick Start

Build a page in pure Java

No server needed — just create components and render:

Page<?> page = new Page<>();
Div<?, ?, ?> container = new Div<>();
container.add(new Paragraph<>().setText("Welcome to JWebMP"));
page.getBody().add(container);

String html = page.toString(true);  // full HTML + queued CSS/JS
String json = page.toString();      // JSON representation of the component tree

Optionally serve it with GuicedEE + Vert.x

Annotate with @PageConfiguration to host the page on the Vert.x HTTP server — this is optional and only needed when you want server-side rendering via Vert.x:

@PageConfiguration(url = "/")
public class HomePage extends Page<HomePage> {

    public HomePage() {
        getBody().add(new H1<>().setText("Hello from JWebMP"));
        getBody().add(new Paragraph<>().setText("Server-rendered, type-safe HTML."));
    }
}
module my.app {
    requires com.jwebmp.core;

    provides com.jwebmp.core.services.IPage
        with my.app.HomePage;
}

Boot GuicedEE — the page is now live:

IGuiceContext.instance().inject();
// Vert.x HTTP server starts, HomePage served at "/"

Handle a click event

Events must be their own named classes — define a top-level or static inner class:

public class ButtonClickEvent extends OnClickAdapter {

    public ButtonClickEvent(Component component) {
        super(component);
    }

    @Override
    public void onClick(AjaxCall<?> call, AjaxResponse<?> response) {
        response.addComponent(new Paragraph<>().setText("Clicked!"));
    }
}

Then attach it to any component:

Div<?, ?, ?> button = new Div<>();
button.setText("Click me");
button.addEvent(new ButtonClickEvent(button));
page.getBody().add(button);

⚠️ Anonymous inner classes and lambdas are not supported for events or features. The framework relies on class identity for serialization, ServiceLoader discovery, and deduplication. Always create a named class.

Add a Feature with typed options

public class TooltipFeature extends Feature<TooltipOptions, TooltipFeature> {

    public TooltipFeature(IComponentHierarchyBase<?, ?> component) {
        super("tooltip", component);
        getOptions().setPlacement("top");
    }

    @Override
    protected void assignFunctionalityToComponent() {
        addQuery(getComponent().asBase().getJQueryID() + "tooltip(" + getOptions() + ");");
    }
}

Use the CSS builder

Div<?, ?, ?> styled = new Div<>();
styled.getCss()
      .getBackground().setBackgroundColor$(ColourNames.AliceBlue);
styled.getCss()
      .getBorder().setBorderWidth(new MeasurementCSSImpl(1, MeasurementTypes.Pixels));
styled.getCss()
      .getFont().setFontSize(new MeasurementCSSImpl(14, MeasurementTypes.Pixels));

📐 Page Render Flow

IGuiceContext.instance().inject()
 └─ JWebMPPreStartup (IGuicePreStartup, sortOrder=15)
     └─ Register JWebMPJacksonModule with ObjectMapper

 HTTP request arrives at @PageConfiguration URL
 └─ IPage instance created (via Guice binding → Page.class)
     └─ IPageConfigurator chain (sorted by sortOrder)
         ├─ CSSLinksInsertPageConfigurator
         │    ├─ RenderBeforeLinks SPIs
         │    ├─ CSS <link> tags inserted into <head>
         │    └─ RenderAfterLinks SPIs
         ├─ ScriptsInsertPageConfigurator
         │    ├─ RenderBeforeScripts SPIs
         │    ├─ <script> tags inserted (by RequirementsPriority)
         │    └─ RenderAfterScripts SPIs
         ├─ TopShelfScriptsInsertPageConfigurator
         │    └─ High-priority scripts in <head>
         └─ ScriptsDynamicPageConfigurator
              ├─ RenderBeforeDynamicScripts SPIs
              ├─ Inline/dynamic <script> blocks
              └─ RenderAfterDynamicScripts SPIs
     └─ page.toString(true) → ful
View on GitHub
GitHub Stars5
CategoryDevelopment
Updated23d ago
Forks1

Languages

Java

Security Score

90/100

Audited on Mar 14, 2026

No findings