Introduction
WebForms Core is a modern server-driven web technology that allows developers to control client-side behavior directly from the server without relying on heavy front-end frameworks such as React, Angular, or Vue. Instead of writing complex JavaScript logic, developers define UI behavior using server-side commands that are executed in the browser by a lightweight JavaScript executor.
After the release of WebForms Core version 2 for multiple programming languages, Java developers can now use this technology seamlessly with Spring Boot (or other back-end frameworks in Java), benefiting from strong typing, clean architecture, and server-side control over the DOM.
In this article, we will explore how to use WebForms Core v2 with Java (Spring Boot) by demonstrating:
Dynamic HTML template loading
Server-side DOM injection
Placeholder replacement
Fetch-based content manipulation
Event-driven UI updates without page reloads
Prerequisites
This article is written and tested using the latest stable versions of the following tools:
The provided code is fully compatible with the latest Java and Spring Boot releases.
Before starting, make sure you have:
A working Spring Boot project
Static file support enabled
The WebForms Core Java classes added to your project
The WebFormsJS script available to the client
WebForms Core Architecture Overview
WebForms Core is based on the Commander–Executor pattern:
Commander (Server Side – Java)
The "WebForms" Java class acts as the Commander , responsible for:
Download the WebForms class according to your desired programming language from the following link:
https://github.com/webforms-core/Web_forms_classes
Executor (Client Side – JavaScript)
The Executor is a JavaScript module called WebFormsJS whose only responsibility is to:
This separation allows Java developers to control UI behavior entirely from the server.
Download WebFormsJS from the following link:
https://github.com/webforms-core/Web_forms
Project Structure Overview
src/
├─ main/
│ ├─ java/
│ │ ├─ com.example.demo/
│ │ │ ├─ DemoApplication.java
│ │ │ └─ MyController.java
│ │ └─ WebFormsCore/
│ │ ├─ WebForms.java
│ │ ├─ Fetch.java
│ │ ├─ HtmlEvent.java
│ │ ├─ HtmlEventListener.java
│ │ ├─ InputPlace.java
│ │ ├─ OutputPlace.java
│ │ ├─ ExtensionWebFormsMethods.java
│ │ ├─ Security.java
│ │ └─ WasmLanguage.java
│ ├─ resources/
│ │ ├─ templates/
│ │ │ └─ default.html
│ │ └─ static/
│ │ ├─ script/
│ │ │ └─ web-forms.js
│ │ └─ api/
│ │ └─ template.html
The WebForms class in Java (due to the limitations and structure of the Java language) is provided separately from the auxiliary classes, unlike other WebForms classes in other programming languages; therefore, the WebFormsCore folder and its classes must be added to the "src/main/java" path.
HTML Templates (Reusable UI Blocks)
"/api/template.html"
This file contains reusable HTML templates defined using the "<template>" tag
<!DOCTYPE html>
<template id="Article">
<section>
<h2>@ArticleTitle</h2>
<p>@ArticleText</p>
</section>
</template>
<template id="Video">
<section>
<h2>@VideoTitle</h2>
<video controls>
<source data-src="@VideoPath" type="video/mp4">
@VideoFallbackText
</video>
</section>
</template>
<template id="Link">
<section>
<h2>@LinksTitle</h2>
<a href="@Link1Url">@Link1Text</a>
</section>
</template>
Each template contains placeholders (e.g. "@VideoTitle") that will later be replaced dynamically by WebForms Core.
Main View (default.html)
<!DOCTYPE html>
<html>
<head>
<title>Using WebForms Core</title>
<script type="module" src="/script/web-forms.js"></script>
</head>
<body>
<h1>Video Template Example</h1>
<button>Click to show video</button>
</body>
</html>
<p th:utext="${WebForms}"></p>
The "th:utext" placeholder injects the WebForms command block generated by the server.
As is clear, in the head section, the script tag has been added with the path to the WebFormsJS module.
Controller: Initial Page Load
@GetMapping("/")
public String PageLoad(Model model) {
WebForms form = new WebForms();
form.setGetEvent("<button>", HtmlEvent.OnClick, "/set-video");
model.addAttribute("WebForms", form.exportToHtmlComment());
return "default";
}
What happens here?
A click event is attached to the "<button>"
Clicking the button sends a GET request to "/set-video"
No JavaScript code is written manually
The event logic is fully server-defined
Dynamic Template Injection (LoadHtml)
form.addText("<body>", Fetch.loadHtml("/api/template.html", "Video"));
Concept: Fetch.loadHtml
The "Fetch.loadHtml" command does not load the HTML file on the server . Instead, it generates a WebForms instruction that will be executed by the client in the browser.
Here’s what happens:
1- The server adds a command like:
[web-forms]
at<body>=@lh/api/template.html,0,Video
gt<body>|<section>-1=r|$[at];VideoTitle|My video|0|1
gt-=r|$[at];VideoPath|https://media.w3.org/2010/05/sintel/trailer.mp4|0|1
gt-=r|$[at];VideoFallbackText|Your browser doesn't support HTML5 video.|0|1
gt-=r|data-src|src|0|1
2. When the HTML page is loaded, WebFormsJS in the browser reads these commands.
3. WebFormsJS fetches "/api/template.html" from the static folder.
4. It extracts the "<template>" with ID Video and injects it into the "<body>" dynamically.
5. Placeholders such as "@VideoTitle", "@VideoPath", and "@VideoFallbackText" are replaced by the client according to the instructions.
This enables component-based UI composition entirely on the client side, while the server only generates the instructions. There is no server-side HTML fetching ; all fetching and DOM manipulation occur in the browser.
Placeholder Replacement (Replace)
form.replace("<body>|<section>-1", "@VideoTitle", "My video", false, true);
form.replace("-", "@VideoPath", "https://media.w3.org/2010/05/sintel/trailer.mp4", false, true);
form.replace("-", "@VideoFallbackText", "Your browser doesn't support HTML5 video.", false, true);
The replace method in WebForms Core instructs the client to replace placeholders in the DOM after the template is injected.
For example:
@VideoTitle → the video title
@VideoPath → the video source URL
@VideoFallbackText → fallback message
All replacements occur on the client side , dynamically updating the DOM without reloading the page .
The image below shows the output of the HTML page. The part highlighted in red is created after clicking the button.
![video_template_example]()
Attribute Manipulation (Advanced replace)
WebForms Core allows dynamic attribute replacement on the client. For example:
form.replace("-", "data-src", "src", false, true);
This converts:
<source data-src="...">
into:
<source src="...">
Why this is useful:
Lazy loading – the resource is loaded only when needed
Deferred attribute activation – you can control the exact timing of loading
Dynamic attribute control – change attributes without triggering immediate browser requests
Note: Using "data-src" prevents the browser from immediately fetching the resource before WebFormsJS executes all template injections and placeholder replacements, improving performance and reducing unnecessary network requests.
Full Server Response (set-video)
@GetMapping("/set-video")
public ResponseEntity<String> PageLoad() {
WebForms form = new WebForms();
form.addText("<body>", Fetch.loadHtml("/api/template.html", "Video"));
form.replace("<body>|<section>-1", "@VideoTitle", "My video", false, true);
form.replace("-", "@VideoPath", "https://media.w3.org/2010/05/sintel/trailer.mp4", false, true);
form.replace("-", "@VideoFallbackText", "Your browser doesn't support HTML5 video.", false, true);
form.replace("-", "data-src", "src", false, true);
return ResponseEntity.ok(form.response());
}
Only WebForms commands are sent to the client — not the entire HTML page .
Result
The page loads instantly.
Clicking the button sends WebForms instructions to the client , which dynamically inject a video section.
No custom JavaScript logic is written by the developer ; WebFormsJS handles execution.
No page reload occurs .
The UI is fully controlled via WebForms instructions from Java , but all DOM manipulation happens in the browser .
Conclusion
WebForms Core v2 for Java provides a structured way to define client-side UI behavior entirely through server-generated instructions. By combining concepts such as HTML template instructions ("Fetch.loadHtml"), client-side placeholder replacement ("replace"), and command-based events, developers can build interactive web applications without writing any manual JavaScript.
Features like "Fetch.loadHtml", "replace", and server-driven events keep Spring Boot applications clean, maintainable, and focused on business logic, while allowing the client to handle all DOM updates efficiently. This approach is especially suitable for form-based systems, dashboards, and applications where UI behavior is tightly coupled with server-side rules.
WebForms Core is designed as an alternative to modern front-end frameworks, allowing developers to efficiently control and update client-side behavior from a stateless server, while still providing a stateful-like and enjoyable experience for developers.