To validate a Struts 2 form without reloading the page, run the normal server-side validation stack through the JSON plugin’s jsonValidation interceptor, then have JavaScript display the returned errors. Send struts.enableJSONValidation=true with the request; use struts.validateOnly=true if the action should stop after validation.
How Struts 2 Ajax validation works
Ajax validation is still server-side validation. The browser sends the form values to Struts, where the validation stack—including applicable visitor validators and the action’s validate() method—runs. Struts returns validation results as JSON, and your JavaScript updates the existing page.
The JSON plugin’s jsonValidation interceptor supplies that response. It must run after validation has populated the action’s errors. The documented jsonValidationWorkflowStack combines the needed behavior; alternatively, configure a stack with validation before jsonValidation. Normal input and success results remain useful for requests that are not handled through Ajax.
Configure the action and choose whether it runs
First define the rules using XML validation files, annotations, or action code. Struts’ validation interceptor runs those rules and creates field and action errors; the workflow interceptor checks for errors and normally returns the input result.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problems- Configure the action to use
jsonValidationWorkflowStack, or use a custom stack that runs validation beforejsonValidation. - Include
struts.enableJSONValidation=truein the Ajax request to activate the JSON validation path. - Set
struts.validateOnly=truewhen the request should validate and stop before the action executes. If the action should run after successful validation, set it tofalse. - If successful action execution should send the browser to a location, configure
jsonActionRedirect; the JSON response can then contain alocationvalue.
With validate-only enabled, a successful response is an empty JSON object, {}. A validation failure is returned with HTTP 400 and JSON errors.
Understand the JSON response
A failed response separates errors that apply to the request or action from errors tied to a particular field:
Rank #2
{
"errors": ["Global error"],
"fieldErrors": {
"email": ["Email is invalid"]
}
}
Use errors for messages that do not belong beside one control, and map each fieldErrors key to the corresponding form control. When the action is model-driven, the interceptor removes the model. prefix from returned field names.
The request parameter names can be changed in stack configuration with validateJsonParam, validateOnlyParam, and noEncodingSetParam. The Struts documentation identifies those overrides as available since version 2.5.9.
Free tools Windows power users keep installed
One-click scans. No signup required.
Keep error targets in the page before validation runs
JavaScript cannot insert a message into an error container that does not exist in the DOM. Keep the field and global error targets in the page from its initial render, including when there are no server-side errors yet. Struts’ documented example uses the ajaxErrorContainers theme for this reason.
For a custom renderer, the following markup uses a simple convention: each field’s message target has a data-error-for value matching the control’s name, and the page has one global error target.
Rank #4
<div data-global-errors aria-live="polite"></div>
<label for="email">Email</label>
<input id="email" name="email" type="email">
<div data-error-for="email" aria-live="polite"></div>
Submit asynchronously and render field errors
This vanilla JavaScript example sends a URL-encoded form, clears stale messages, and renders the returned errors as text. Its data-error-for and data-global-errors attributes are application markup conventions, not Struts-specific names.
const form = document.querySelector("#signup-form");
form.addEventListener("submit", async (event) => {
event.preventDefault();
const globalErrors = document.querySelector("[data-global-errors]");
globalErrors.replaceChildren();
form.querySelectorAll("[data-error-for]").forEach((target) => {
target.replaceChildren();
});
const params = new URLSearchParams(new FormData(form));
params.set("struts.enableJSONValidation", "true");
params.set("struts.validateOnly", "true");
let response;
try {
response = await fetch(form.action, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8" },
body: params
});
} catch (error) {
globalErrors.textContent = "Could not contact the server. Check your connection and try again.";
return;
}
let result;
try {
result = await response.json();
} catch (error) {
globalErrors.textContent = "The server returned an unreadable response.";
return;
}
if (!response.ok && response.status !== 400) {
globalErrors.textContent = "The request could not be completed. Try again later.";
return;
}
(result.errors || []).forEach((message) => {
const item = document.createElement("p");
item.textContent = message;
globalErrors.append(item);
});
Object.entries(result.fieldErrors || {}).forEach(([fieldName, messages]) => {
const target = Array.from(form.querySelectorAll("[data-error-for]"))
.find((element) => element.dataset.errorFor === fieldName);
if (!target) return;
messages.forEach((message) => {
const item = document.createElement("p");
item.textContent = message;
target.append(item);
});
});
if (response.status === 400 && !result.errors?.length && !Object.keys(result.fieldErrors || {}).length) {
globalErrors.textContent = "The form could not be validated.";
}
});
Using textContent treats messages as text rather than markup. The example treats HTTP 400 as the documented validation-failure status, handles other HTTP failures separately, and reports network or unreadable-response problems without presenting them as field validation errors.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Best Value
Choose the right kind of validation
Struts supports validators including required, required-string, integer, date, email, URL, string length, regex, expression, and visitor validation. Prefer a field-specific validator when the error belongs to a particular control; its message can then appear beside that control.
| Approach | Where rules run | How the user gets feedback | Key trade-off |
|---|---|---|---|
| Browser-native constraints | In the browser | Typically during browser validation before submission | Useful for quick feedback, but not a replacement for server-side rules. |
| Struts Ajax validation | On the server, through the Struts validation stack | JavaScript renders the JSON errors without a full-page reload | Requires an Ajax request, persistent message targets, and client-side response handling. |
| Regular form submission | On the server, through the Struts validation stack | The action returns its normal result, commonly the input result when errors exist |
Uses the regular page flow rather than updating the current form asynchronously. |
Browser constraints and Struts validation can complement one another: the browser can catch simple input problems early, while server-side validation remains authoritative. The Struts documentation says version 7.4.0 added HTML5 constraint attributes through the html5 theme when struts.ui.html5.constraints=true. That browser feature is distinct from server-backed Ajax validation. The same documentation says older pure-JavaScript client validation was deprecated in 7.4.0 and removed in 8.0.0; do not confuse that legacy feature or the Dojo-based Ajax theme with the JSON validation flow described here.
Remember what Ajax changes—and what it does not
An Ajax call is still an ordinary HTTP request to Struts. The difference is that JavaScript consumes the response rather than navigating directly to a rendered page. Struts can return JSON, HTML, XML, text, or another script; the JSON plugin is the documented route for this JSON validation response.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →

