You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2026/08/25 06:08:43 UTC
(struts-site) branch docs/html5-constraint-validation created (now acbface9d)
This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a change to branch docs/html5-constraint-validation
in repository https://gitbox.apache.org/repos/asf/struts-site.git
at acbface9d docs: fix the stringlength example's direction (server accepts, browser blocks)
This branch includes the following new commits:
new 0bda63ed4 docs: document html5 constraint validation, deprecate the JS validator
new 2e9203d34 docs: stop asserting a specific version for the html5.constraints default flip
new 32e721803 docs: add the regex validator's fourth pattern gate, generalize the trim note
new acbface9d docs: fix the stringlength example's direction (server accepts, browser blocks)
The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(struts-site) 02/04: docs: stop asserting a specific version for the html5.constraints default flip
Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch docs/html5-constraint-validation
in repository https://gitbox.apache.org/repos/asf/struts-site.git
commit 2e9203d342c9bf92649dec93292438207134b0f3
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Tue Aug 25 00:17:20 2026 +0200
docs: stop asserting a specific version for the html5.constraints default flip
The shipped javadoc and default.properties deliberately say the
struts.ui.html5.constraints default is "expected to flip in a future major
release" rather than naming 8.0.0, since the release version is chosen at
release time from the accumulated semver impact. The docs page asserted "in
Struts 8.0.0" instead, which is a firmer commitment than the code itself
makes. Softened to match the code's wording, with WW-5696 linked so the claim
stays traceable.
Also makes every other "removed in 8.0.0" claim (the JS validator's removal)
cite WW-5694/WW-5696 inline rather than floating as a bare assertion. Naming
8.0.0 for that removal is kept as-is: it's a major-version removal, already
committed to in Form.java's own @Deprecated(since = "7.4.0", forRemoval =
true) javadoc, and WW-5696 is filed against it.
Co-Authored-By: Claude Opus 5 <no...@anthropic.com>
---
source/core-developers/ajax-client-side-validation.md | 3 ++-
source/core-developers/client-side-validation.md | 5 +++--
source/tag-developers/css-xhtml-theme.md | 11 +++++++----
source/tag-developers/xhtml-theme.md | 11 +++++++----
4 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/source/core-developers/ajax-client-side-validation.md b/source/core-developers/ajax-client-side-validation.md
index 45012487e..2f52ccff5 100644
--- a/source/core-developers/ajax-client-side-validation.md
+++ b/source/core-developers/ajax-client-side-validation.md
@@ -15,7 +15,8 @@ parent:
## Description
AJAX-based client side validation improves upon [Pure JavaScript Client Side Validation](client-side-validation#pure-javascript-client-side-validation-deprecated)
-(deprecated since Struts 7.4.0, removed in 8.0.0) by using a combination of JavaScript, DOM manipulation, and remote server communication. Unlike the pure client side
+(deprecated since 7.4.0 [WW-5694](https://issues.apache.org/jira/browse/WW-5694), removed in 8.0.0
+[WW-5696](https://issues.apache.org/jira/browse/WW-5696)) by using a combination of JavaScript, DOM manipulation, and remote server communication. Unlike the pure client side
implementation, AJAX-based validation communicates with the server. This means all your validation rules that worked
when submitting a form will still work within the browser.
diff --git a/source/core-developers/client-side-validation.md b/source/core-developers/client-side-validation.md
index e281ba7ea..5b4836b45 100644
--- a/source/core-developers/client-side-validation.md
+++ b/source/core-developers/client-side-validation.md
@@ -39,8 +39,9 @@ theme](../tag-developers/html5-theme#using-the-html5-theme)). There is no per-fo
unlike the deprecated JavaScript validator, this feature does not use `<s:form validate="true">`. Once the
constant is on and a field's theme is `html5`, its validators are consulted automatically.
-> The constant defaults to `false` in 7.4.0 so existing `html5`-theme forms keep rendering unchanged. The
-> default is expected to flip to `true` in Struts 8.0.0.
+> The constant defaults to `false` so existing `html5`-theme forms keep rendering unchanged. The default is
+> expected to flip to `true` in a future major release, tracked by
+> [WW-5696](https://issues.apache.org/jira/browse/WW-5696).
### The governing rule: never false-reject
diff --git a/source/tag-developers/css-xhtml-theme.md b/source/tag-developers/css-xhtml-theme.md
index 44176e72e..0cd207e23 100644
--- a/source/tag-developers/css-xhtml-theme.md
+++ b/source/tag-developers/css-xhtml-theme.md
@@ -15,8 +15,9 @@ The _css_xhtml theme_ provides all the basics that the [simple theme](simple-the
- Labels for each of the HTML [Struts Tags](struts-tags), placed according to the CSS stylesheet
- [Validation](../core-developers/validation) and error reporting
- [Pure JavaScript Client Side Validation](../core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated)
- using 100% JavaScript on the browser — **deprecated since Struts 7.4.0, removed in 8.0.0**; use the
- [html5 theme](html5-theme) instead
+ using 100% JavaScript on the browser — deprecated since 7.4.0
+ ([WW-5694](https://issues.apache.org/jira/browse/WW-5694)), removed in 8.0.0
+ ([WW-5696](https://issues.apache.org/jira/browse/WW-5696)); use the [html5 theme](html5-theme) instead
## Wrapping the Simple Theme
@@ -71,7 +72,8 @@ The head includes a style sheet. The contents of **styles.css** are:
The css_xhtml [form](form-tag) template is almost exactly like the _xhtml form template_ , including support for
[Pure JavaScript Client Side Validation](../core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated)
-(deprecated since Struts 7.4.0, removed in 8.0.0). The difference is that instead of printing out an opening and closing
+(deprecated since 7.4.0 [WW-5694](https://issues.apache.org/jira/browse/WW-5694), removed in 8.0.0
+[WW-5696](https://issues.apache.org/jira/browse/WW-5696)). The difference is that instead of printing out an opening and closing
`<table>` element, there are no elements. Instead, the CSS rules for the individual HTML tags are assumed to handle all
display logic. However, as noted, client-side validation is still supported.
@@ -79,6 +81,7 @@ display logic. However, as noted, client-side validation is still supported.
The css_xhtml [form](form-tag) template is almost exactly like the _xhtml form template_ , including support for
[Pure JavaScript Client Side Validation](../core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated)
-(deprecated since Struts 7.4.0, removed in 8.0.0). The only difference is that instead of printing out an opening and
+(deprecated since 7.4.0 [WW-5694](https://issues.apache.org/jira/browse/WW-5694), removed in 8.0.0
+[WW-5696](https://issues.apache.org/jira/browse/WW-5696)). The only difference is that instead of printing out an opening and
closing `<table>` element, there are no elements. Instead, the CSS rules for the individual HTML tags are assumed to
handle all display logic. However, as noted, client side validation is still supported.
diff --git a/source/tag-developers/xhtml-theme.md b/source/tag-developers/xhtml-theme.md
index abed1e85f..50297eea9 100644
--- a/source/tag-developers/xhtml-theme.md
+++ b/source/tag-developers/xhtml-theme.md
@@ -20,8 +20,9 @@ The xhtml provides all the basics that the [simple theme](simple-theme) provides
the `labelposition` attribute)
- [Validation](../core-developers/validation) and error reporting
- [Pure JavaScript Client Side Validation](../core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated)
- using 100% JavaScript on the browser — **deprecated since Struts 7.4.0, removed in 8.0.0**; use the
- [html5 theme](html5-theme) instead
+ using 100% JavaScript on the browser — deprecated since 7.4.0
+ ([WW-5694](https://issues.apache.org/jira/browse/WW-5694)), removed in 8.0.0
+ ([WW-5696](https://issues.apache.org/jira/browse/WW-5696)); use the [html5 theme](html5-theme) instead
## Wrapping the Simple Theme
@@ -96,7 +97,8 @@ The head template imports a style sheet. The contents of **styles.css** are:
The xhtml form template sets up the wrapping table around all the other form elements. In addition to creating this
wrapping table, the opening and closing templates also, if the `validate` parameter is set to true, enable
[Pure JavaScript Client Side Validation](../core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated)
-(deprecated since Struts 7.4.0, removed in 8.0.0).
+(deprecated since 7.4.0 [WW-5694](https://issues.apache.org/jira/browse/WW-5694), removed in 8.0.0
+[WW-5696](https://issues.apache.org/jira/browse/WW-5696)).
{% highlight freemarker %}
{% remote_file_content https://raw.githubusercontent.com/apache/struts/main/core/src/main/resources/template/xhtml/form.ftl %}
@@ -113,7 +115,8 @@ The closing template, `form-close.ftl`:
The xhtml form template sets up the wrapping table around all the other [xhtml theme](xhtml-theme) form elements.
In addition to creating this wrapping table, the opening and closing templates also, if the `validate` parameter is set
to `true`, enable [Pure JavaScript Client Side Validation](../core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated)
-(deprecated since Struts 7.4.0, removed in 8.0.0).
+(deprecated since 7.4.0 [WW-5694](https://issues.apache.org/jira/browse/WW-5694), removed in 8.0.0
+[WW-5696](https://issues.apache.org/jira/browse/WW-5696)).
See the **form.ftl** contents:
(struts-site) 03/04: docs: add the regex validator's fourth pattern gate, generalize the trim note
Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch docs/html5-constraint-validation
in repository https://gitbox.apache.org/repos/asf/struts-site.git
commit 32e721803f0eb6cebadef6662eb311c536102d44
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Tue Aug 25 00:24:03 2026 +0200
docs: add the regex validator's fourth pattern gate, generalize the trim note
The regex row promised pattern whenever text-entry, caseSensitive="true",
trim="false" and ECMAScript-safe held, but StrutsHtmlConstraintProvider has a
fourth gate: email and creditcard validators are excluded even then, since
both extend RegexFieldValidator but carry grammars the browser doesn't share.
Also generalizes the trim="false" explanation: StringLengthFieldValidator.trim
defaults to true just like RegexFieldValidator.trim, so minlength/maxlength are
emitted just as rarely as pattern is, for the same reason (server measures/
matches the trimmed value, browser sees the raw one). The page previously
warned about this only for pattern, which understated stringlength's own
reach. Reworked into one shared paragraph covering both.
Co-Authored-By: Claude Opus 5 <no...@anthropic.com>
---
source/core-developers/client-side-validation.md | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/source/core-developers/client-side-validation.md b/source/core-developers/client-side-validation.md
index 5b4836b45..d81b9c3ea 100644
--- a/source/core-developers/client-side-validation.md
+++ b/source/core-developers/client-side-validation.md
@@ -69,7 +69,7 @@ an `int` or `double` validator is attached to it.
| `requiredstring` | `required` | on text-entry controls (`text`, `search`, `tel`, `password`, `email`, `url`) and `textarea` |
| `required` | `required` | only on `radio` and `file` |
| `stringlength` | `minlength` / `maxlength` | on text-entry or `textarea`, and only if the validator has `trim="false"`; each attribute is added only if actually configured |
-| `regex` | `pattern` | on text-entry controls only, and only if `caseSensitive="true"`, `trim="false"`, and the regex is ECMAScript-safe (see below) |
+| `regex` | `pattern` | on text-entry controls only, and only if `caseSensitive="true"`, `trim="false"`, the regex is ECMAScript-safe (see below), and the validator is not an `email` or `creditcard` validator (both extend `RegexFieldValidator` but carry grammars the browser does not share) |
| `int`, `short`, `long` | `min` / `max` | only when the control is already `type="number"` or `type="range"` |
| `double` | `min` / `max` | same as above; only inclusive bounds are emitted — exclusive bounds have no HTML equivalent and are omitted |
| `date` | — | nothing yet; temporal `min`/`max` is deferred to a future release |
@@ -77,7 +77,8 @@ an `int` or `double` validator is attached to it.
| `fieldexpression`, `expression`, `conversion`, visitor validators | — | never emitted |
| any validator carrying a message | `data-msg-<validatorType>` | always added, including for validators that emit no constraint attribute at all |
-Two of these conditions are easy to miss and sharply limit how often `required` and `pattern` actually show up:
+Two of these conditions are easy to miss and sharply limit how often `required`, `minlength`/`maxlength`,
+and `pattern` actually show up:
**`required` is split across two validators, and they don't behave alike.** `requiredstring` fails on
null, empty, and (by default) blank values, so it is strictly stricter than the browser's `required` — safe
@@ -89,12 +90,15 @@ Only `radio` and `file` controls omit their parameter entirely when left empty,
control types where plain `required` agrees with the server — which is why the table above emits `required`
for the `required` validator on those two types alone.
-**`pattern` needs `trim="false"`, which is not the default.** `RegexFieldValidator.trim` defaults to
-`true`, so the server matches the field's *trimmed* value while an HTML `pattern` attribute matches the
-*raw* one. A regex like `[a-z]+` would accept `"abc "` server-side while the browser blocks it. Because of
-this, `pattern` is only ever emitted for validators explicitly configured with `trim="false"` — which most
-existing `regex` validators are not. In practice, expect `pattern` to show up rarely until applications
-start setting `trim="false"` deliberately for fields where it's safe.
+**Both `minlength`/`maxlength` and `pattern` need `trim="false"`, which is not the default.** Both
+`StringLengthFieldValidator.trim` and `RegexFieldValidator.trim` default to `true`, so the server measures
+or matches the field's *trimmed* value while the HTML attribute constrains the *raw* one. A `stringlength`
+validator with `maxLength="4"` would reject `"abcd "` server-side after trimming while the browser, seeing
+five raw characters, would block it first — and a `regex` of `[a-z]+` would accept `"abc "` server-side
+while the browser blocks it. Because of this, `minlength`/`maxlength` and `pattern` are only ever emitted
+for validators explicitly configured with `trim="false"` — which most existing `stringlength` and `regex`
+validators are not. In practice, expect both to show up rarely until applications start setting
+`trim="false"` deliberately for fields where it's safe.
**ECMAScript-safe** means the regex uses only constructs that mean the same thing in Java's regex engine
and in the browser's: literals, `\d`/`\w` and their negations, character classes without POSIX or Unicode
(struts-site) 01/04: docs: document html5 constraint validation, deprecate the JS validator
Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch docs/html5-constraint-validation
in repository https://gitbox.apache.org/repos/asf/struts-site.git
commit 0bda63ed416813bdfc45cc0df7f44e1c26fff963
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Tue Aug 25 00:13:48 2026 +0200
docs: document html5 constraint validation, deprecate the JS validator
Rewrites client-side-validation.md around the html5 theme's new HTML5
constraint-validation attributes (struts.ui.html5.constraints), including the
never-false-reject rule, the full validator-to-attribute mapping, the
trim="false"/caseSensitive="true" conditions on stringlength/regex, the
never-change-the-type rule, data-msg-* hooks, the requiredLabel/required
distinction, and the swappable HtmlConstraintProvider extension point.
Deprecates the older generated-JavaScript client-side validator (xhtml/
css_xhtml themes, <s:form validate="true">) per WW-5694, removed in 8.0.0 per
WW-5696: deletes pure-java-script-client-side-validation.md, repoints its
inbound links (xhtml-theme.md, css-xhtml-theme.md, ajax-client-side-validation.md)
to the deprecated section of the rewritten page, adds deprecation banners to
client-validation-example.md and form-tag.md's validate attribute.
Drops the deleted page's claim that client-side messages are not
internationalized: ValidatorSupport.getMessage resolves through
DelegatingValidatorContext and textProviderFactory, so they always were.
Co-Authored-By: Claude Opus 5 <no...@anthropic.com>
---
.../core-developers/ajax-client-side-validation.md | 4 +-
source/core-developers/client-side-validation.md | 171 ++++++++++++++++-----
.../core-developers/client-validation-example.md | 6 +
.../pure-java-script-client-side-validation.md | 50 ------
source/tag-developers/css-xhtml-theme.md | 21 +--
source/tag-developers/form-tag.md | 7 +
source/tag-developers/xhtml-theme.md | 11 +-
7 files changed, 168 insertions(+), 102 deletions(-)
diff --git a/source/core-developers/ajax-client-side-validation.md b/source/core-developers/ajax-client-side-validation.md
index b9e47ed69..45012487e 100644
--- a/source/core-developers/ajax-client-side-validation.md
+++ b/source/core-developers/ajax-client-side-validation.md
@@ -14,8 +14,8 @@ parent:
## Description
-AJAX-based client side validation improves upon [Pure JavaScript Client Side Validation](pure-java-script-client-side-validation)
-by using a combination of JavaScript, DOM manipulation, and remote server communication. Unlike the pure client side
+AJAX-based client side validation improves upon [Pure JavaScript Client Side Validation](client-side-validation#pure-javascript-client-side-validation-deprecated)
+(deprecated since Struts 7.4.0, removed in 8.0.0) by using a combination of JavaScript, DOM manipulation, and remote server communication. Unlike the pure client side
implementation, AJAX-based validation communicates with the server. This means all your validation rules that worked
when submitting a form will still work within the browser.
diff --git a/source/core-developers/client-side-validation.md b/source/core-developers/client-side-validation.md
index 20a8dabad..e281ba7ea 100644
--- a/source/core-developers/client-side-validation.md
+++ b/source/core-developers/client-side-validation.md
@@ -14,57 +14,156 @@ parent:
## Basics
-The framework adds support for client-side validation on top of the standard validation framework.
+Since Struts 7.4.0, the [html5 theme](../tag-developers/html5-theme) can derive HTML5 constraint-validation
+attributes (`required`, `minlength`, `maxlength`, `pattern`, `min`, `max`) directly from a field's
+server-side [validators](validation), so the browser rejects obviously-invalid input before the form is
+even submitted. This replaces the older, generated-JavaScript validator used by the _xhtml theme_ and
+_css_xhtml theme_, which is now deprecated — see [Pure JavaScript Client Side Validation
+(deprecated)](#pure-javascript-client-side-validation-deprecated) below.
-Client-side validation can be enabled on a per-form basis by specifying `validate="true"` in the _form_ tag.
+There is also [AJAX Client Side Validation](ajax-client-side-validation), which runs the full server-side
+validation stack (including visitor validators and `validate()`) over AJAX and is unaffected by any of this.
-```jsp
-<s:form name="test" action="javascriptValidation" validate="true">
- ...
-</s:form>
-```
+## HTML5 Constraint Validation
-If a `name` for the form is not given, the action mapping name will be used as the form name. Otherwise, a correct
-`action` and `namespace` attributes must be provided to the `<saf:form>` tag.
+### Enabling it
-## Referencing "submitProfile" in the "/user" namespace
+HTML5 constraint validation is off by default. Turn it on with the `struts.ui.html5.constraints` constant:
-```jsp
-<s:form namespace="/user" action="submitProfile" validate="true">
- ...
-</s:form>
+```properties
+struts.ui.html5.constraints=true
+```
+
+It only has an effect on fields rendered with the `html5` theme (see [Using the HTML5
+theme](../tag-developers/html5-theme#using-the-html5-theme)). There is no per-form opt-in attribute —
+unlike the deprecated JavaScript validator, this feature does not use `<s:form validate="true">`. Once the
+constant is on and a field's theme is `html5`, its validators are consulted automatically.
+
+> The constant defaults to `false` in 7.4.0 so existing `html5`-theme forms keep rendering unchanged. The
+> default is expected to flip to `true` in Struts 8.0.0.
+
+### The governing rule: never false-reject
+
+The mapping is deliberately conservative. A constraint is emitted only when the browser cannot reject
+input the server would have accepted. If the browser rejected something the server allows, the user would
+be stuck with a form that will not submit and no explanation why. Being conservative simply costs a field
+its client-side check — that's a harmless, quiet failure mode, so the mapping always chooses it over the
+alternative.
+
+The clearest consequence of this rule: **Struts never sets or changes an input's `type`.** A field stays
+whatever `type` the developer gave it. In particular:
+
+- Switching a field to `type="number"` would reject a value like `1234,50`, which the framework's
+ locale-aware numeric conversion happily accepts in a comma-decimal locale.
+- The browsers' `email` and `url` input grammars don't match `EmailValidator` and `UrlValidator`.
+
+So `min`/`max` range constraints are only ever added to a control the developer *already* made numeric
+(`type="number"` or `type="range"`) — Struts will never promote a plain text field into one just because
+an `int` or `double` validator is attached to it.
+
+### Mapping table
+
+| Validator | Emits | Condition |
+|---|---|---|
+| `requiredstring` | `required` | on text-entry controls (`text`, `search`, `tel`, `password`, `email`, `url`) and `textarea` |
+| `required` | `required` | only on `radio` and `file` |
+| `stringlength` | `minlength` / `maxlength` | on text-entry or `textarea`, and only if the validator has `trim="false"`; each attribute is added only if actually configured |
+| `regex` | `pattern` | on text-entry controls only, and only if `caseSensitive="true"`, `trim="false"`, and the regex is ECMAScript-safe (see below) |
+| `int`, `short`, `long` | `min` / `max` | only when the control is already `type="number"` or `type="range"` |
+| `double` | `min` / `max` | same as above; only inclusive bounds are emitted — exclusive bounds have no HTML equivalent and are omitted |
+| `date` | — | nothing yet; temporal `min`/`max` is deferred to a future release |
+| `email`, `url`, `creditcard` | — | never emitted |
+| `fieldexpression`, `expression`, `conversion`, visitor validators | — | never emitted |
+| any validator carrying a message | `data-msg-<validatorType>` | always added, including for validators that emit no constraint attribute at all |
+
+Two of these conditions are easy to miss and sharply limit how often `required` and `pattern` actually show up:
+
+**`required` is split across two validators, and they don't behave alike.** `requiredstring` fails on
+null, empty, and (by default) blank values, so it is strictly stricter than the browser's `required` — safe
+to emit on any text-entry control. Plain `required`, however, only fails on a null value, an empty array,
+or an empty collection. That means an empty text input (which submits `""`, not nothing), a `select` with
+an empty-valued option, and an **unticked checkbox** (`CheckboxInterceptor` substitutes the parameter
+`"false"` for it) all pass server-side validation while a browser `required` attribute would block them.
+Only `radio` and `file` controls omit their parameter entirely when left empty, so those are the only two
+control types where plain `required` agrees with the server — which is why the table above emits `required`
+for the `required` validator on those two types alone.
+
+**`pattern` needs `trim="false"`, which is not the default.** `RegexFieldValidator.trim` defaults to
+`true`, so the server matches the field's *trimmed* value while an HTML `pattern` attribute matches the
+*raw* one. A regex like `[a-z]+` would accept `"abc "` server-side while the browser blocks it. Because of
+this, `pattern` is only ever emitted for validators explicitly configured with `trim="false"` — which most
+existing `regex` validators are not. In practice, expect `pattern` to show up rarely until applications
+start setting `trim="false"` deliberately for fields where it's safe.
+
+**ECMAScript-safe** means the regex uses only constructs that mean the same thing in Java's regex engine
+and in the browser's: literals, `\d`/`\w` and their negations, character classes without POSIX or Unicode
+property syntax, grouping, alternation, anchors, and bounded quantifiers. Notably, **`\s` and `\S` are
+excluded** — Java's `\s` is ASCII-only by default while ECMAScript's `\s` covers the wider Unicode
+whitespace set, so a pattern like `^\S+$` would accept a value containing a non-breaking space server-side
+and reject it in the browser. Any regex using a construct outside this allowlist simply gets no `pattern`
+attribute at all — it is never rejected loudly, it just quietly doesn't get a client-side check.
+
+### `data-msg-*` attributes
+
+Every validator carrying a message — even one that emits no HTML constraint attribute at all — adds a
+`data-msg-<validatorType>` attribute (for example `data-msg-email`, `data-msg-regex`) holding the
+validator's fully resolved, internationalized message. **Struts ships no JavaScript that reads these.**
+They exist purely as a hook: an application can write its own script to read `data-msg-*` and show
+whichever messages it wants, in whatever way it wants, including for validators (like `email` or
+`creditcard`) that never get a native browser check.
+
+### `requiredLabel` is unrelated to the `required` attribute
+
+This is a common point of confusion: the `requiredLabel` tag attribute only controls whether a visual
+marker (usually `*`) is drawn next to a field's label. It has no connection to the HTML `required`
+attribute described above, and setting `requiredLabel="true"` does not make a field required in the
+browser — the two are decided completely independently.
+
+### Extension point: `HtmlConstraintProvider`
+
+The mapping above is implemented by `StrutsHtmlConstraintProvider`, the default implementation of the
+`HtmlConstraintProvider` interface, registered under the `struts.htmlConstraintProvider` constant:
+
+```properties
+struts.htmlConstraintProvider=struts
```
-Technically, the form's action attribute can refer to a "path" that includes the namespace and action as a URI.
-But, client-side validation **requires** that the action name and namespeact to be set separately.
+An application that wants a less conservative mapping — for example, treating an `email` validator as
+`type="email"`, or emitting `pattern` for case-insensitive regexes by rewriting them — can register its own
+`HtmlConstraintProvider` implementation under this constant instead of the default. This is the escape
+hatch for every limitation described above: the framework's own mapping stays deliberately conservative,
+but nothing stops an application from replacing it with one that fits its own validators and locales.
+
+## Pure JavaScript Client Side Validation (deprecated)
+
+> **Deprecated since Struts 7.4.0 ([WW-5694](https://issues.apache.org/jira/browse/WW-5694)), removed in
+> Struts 8.0.0 ([WW-5696](https://issues.apache.org/jira/browse/WW-5696)).** New applications should use
+> the [html5 theme's constraint validation](#html5-constraint-validation) described above instead.
-## Won't work with client-side validation!
+The `<s:form validate="true">` attribute enables an older client-side validation mechanism, used by the
+_xhtml theme_ and _css_xhtml theme_. It uses 100% client-side JavaScript, generated from the same
+validation configuration used server-side, to try to reject bad input before the form is submitted:
```jsp
-<s:form action="/user/submitProfile.action" validate="true">
+<s:form name="test" action="javascriptValidation" validate="true">
...
</s:form>
-
```
-All the usual [validation configuration](validation) steps apply to client-side validation. Client-side validation
-uses the same validation rules as server-side validation. If server-side validation doesn't work, then client-side
-validation won't work either.
+If a `name` for the form is not given, the action mapping name is used as the form name. Otherwise, a
+correct `action` and `namespace` attribute must be provided to the `<s:form>` tag — client-side validation
+requires the action name and namespace to be resolvable separately, so a form whose `action` is given as a
+full URI (for example `<s:form action="/user/submitProfile.action" validate="true">`) will not get
+client-side validation, even though the form still works.
-## The left hand doesn't know ...
-
-> The required attribute on many _Struts Tags_ is not integrated with client-side validation! The tag attribute is used
-> by certain themes (like xhtml) to put a visual marker (usually '*') next to the field. The tag doesn't know
-> if the validation system actually "requires" the field or not.
+Because the validation logic is repeated in generated JavaScript, only a subset of validators is
+supported (`required`, `requiredstring`, `stringlength`, `regex`, `email`, `url`, `int`, `double`), it is
+not available for visitor validators at all, and — being a separate implementation of each validator's
+logic — some values the JavaScript accepts may still be rejected server-side, or vice versa. This is one of
+the reasons it is being replaced: the html5 theme's constraint validation above is derived directly from
+the real validators, rather than reimplementing them in JavaScript.
## Example
-See [Client Validation example](client-validation-example) for a complete example of client-side validation.
-
-## Client Side Validation Types
-
-There are two styles of client side validation.
-
-|[Pure JavaScript Client Side Validation](pure-java-script-client-side-validation)|Used by the _xhtml theme_ and _css_xhtml theme_|
-|-----------------------------------------------------|--------------------------------------------------|
-|[AJAX Client Side Validation](ajax-client-side-validation)|Use to used by the _ajax theme_ |
+See [Client Validation example](client-validation-example) for a complete, though now-deprecated, example
+of the JavaScript-based client-side validation described above.
diff --git a/source/core-developers/client-validation-example.md b/source/core-developers/client-validation-example.md
index 751e08121..3e3d5573a 100644
--- a/source/core-developers/client-validation-example.md
+++ b/source/core-developers/client-validation-example.md
@@ -8,6 +8,12 @@ parent:
# Client Validation Example
+> **Deprecated since Struts 7.4.0 ([WW-5694](https://issues.apache.org/jira/browse/WW-5694)), removed in
+> Struts 8.0.0 ([WW-5696](https://issues.apache.org/jira/browse/WW-5696)).** This example walks through the
+> generated-JavaScript client-side validator (`<s:form validate="true">`) used by the _xhtml theme_ and
+> _css_xhtml theme_. New applications should use the [html5 theme's constraint
+> validation](client-side-validation#html5-constraint-validation) instead.
+
Let's create a Client-Side validation workflow, step by step. The `validate` attribute is set to `true`.
> Note: Some themes do not support client-side validation.
diff --git a/source/core-developers/pure-java-script-client-side-validation.md b/source/core-developers/pure-java-script-client-side-validation.md
deleted file mode 100644
index 43fde3e84..000000000
--- a/source/core-developers/pure-java-script-client-side-validation.md
+++ /dev/null
@@ -1,50 +0,0 @@
----
-layout: default
-title: Pure JavaScript Client Side Validation
-parent:
- title: Client Side Validation
- url: client-side-validation
----
-
-# Pure JavaScript Client Side Validation
-{:.no_toc}
-
-* Will be replaced with the ToC, excluding a header
-{:toc}
-
-## Description
-
-Pure JavaScript client side validation is the simplest but least feature-rich type of [Client Side Validation](client-side-validation).
-This type of validation uses 100% client-side JavaScript code to try to validate the values entered by the user.
-Because the validation logic is actually repeated in the JavaScript code, it is important to understand that
-some values will be considered acceptable by the JavaScript code but will be marked as unacceptable by the server-side [Validation](validation).
-
-Only the following validators are supported:
-
-* required validator
-* requiredstring validator
-* stringlength validator
-* regex validator
-* email validator
-* url validator
-* int validator
-* double validator
-
-> JavaScript client validation is not available for visitor validations.
-
-## Error reporting
-
-Because client side validation does not talk to the server, the theme (_xhtml theme_ or _css_xhtml theme_ ) is responsible
-for properly manipulating the HTML DOM to display the error message inline. The JavaScript that is responsible for doing
-this logic is `validation.js` and can be found in each theme.
-
-> Errors are reported using the default validation message, not the internationalized version that the server-side might
-> be aware of. This is a known issue. You may want to try the [AJAX Client Side Validation](ajax-client-side-validation)
-> for messages that are fully internationalized.
-
-## Additional Validator Support
-
-If you wish to add additional validator support beyond those listed, you may override the _xhtml theme_ template
-`form-close-validate.ftl`. This file contains the JavaScript that tries to validate each user-entered value from within
-the browser. The _css_xhtml theme_ extends the _xhtml theme_ and therefore doesn't have its own `form-close-validate.ftl`
-template.
diff --git a/source/tag-developers/css-xhtml-theme.md b/source/tag-developers/css-xhtml-theme.md
index a6d3e73e0..44176e72e 100644
--- a/source/tag-developers/css-xhtml-theme.md
+++ b/source/tag-developers/css-xhtml-theme.md
@@ -14,8 +14,9 @@ The _css_xhtml theme_ provides all the basics that the [simple theme](simple-the
[textfield](textfield-tag), [select](select-tag), etc)
- Labels for each of the HTML [Struts Tags](struts-tags), placed according to the CSS stylesheet
- [Validation](../core-developers/validation) and error reporting
-- [Pure JavaScript Client Side Validation](../core-developers/pure-java-script-client-side-validation) using 100%
- JavaScript on the browser
+- [Pure JavaScript Client Side Validation](../core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated)
+ using 100% JavaScript on the browser — **deprecated since Struts 7.4.0, removed in 8.0.0**; use the
+ [html5 theme](html5-theme) instead
## Wrapping the Simple Theme
@@ -69,15 +70,15 @@ The head includes a style sheet. The contents of **styles.css** are:
### Form template
The css_xhtml [form](form-tag) template is almost exactly like the _xhtml form template_ , including support for
-[Pure JavaScript Client Side Validation](../core-developers/pure-java-script-client-side-validation). The difference
-is that instead of printing out an opening and closing `<table>` element, there are no elements. Instead, the CSS rules
-for the individual HTML tags are assumed to handle all display logic. However, as noted, client-side validation is still
-supported.
+[Pure JavaScript Client Side Validation](../core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated)
+(deprecated since Struts 7.4.0, removed in 8.0.0). The difference is that instead of printing out an opening and closing
+`<table>` element, there are no elements. Instead, the CSS rules for the individual HTML tags are assumed to handle all
+display logic. However, as noted, client-side validation is still supported.
### css_xhtml form template
The css_xhtml [form](form-tag) template is almost exactly like the _xhtml form template_ , including support for
-[Pure JavaScript Client Side Validation](../core-developers/pure-java-script-client-side-validation). The only
-difference is that instead of printing out an opening and closing `<table>` element, there are no elements. Instead,
-the CSS rules for the individual HTML tags are assumed to handle all display logic. However, as noted, client side
-validation is still supported.
+[Pure JavaScript Client Side Validation](../core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated)
+(deprecated since Struts 7.4.0, removed in 8.0.0). The only difference is that instead of printing out an opening and
+closing `<table>` element, there are no elements. Instead, the CSS rules for the individual HTML tags are assumed to
+handle all display logic. However, as noted, client side validation is still supported.
diff --git a/source/tag-developers/form-tag.md b/source/tag-developers/form-tag.md
index 52684722e..c516e3730 100644
--- a/source/tag-developers/form-tag.md
+++ b/source/tag-developers/form-tag.md
@@ -41,3 +41,10 @@ There are two flavours [Client Side Validation](../core-developers/client-side-v
are using (xhtml, ajax, etc). If you are using the [xhtml theme](xhtml-theme) or [css_xhtml theme](css-xhtml-theme),
pure client side validation will be used. Read the [Client Side Validation](../core-developers/client-side-validation)
docs for more information.
+
+> **`validate` is deprecated since Struts 7.4.0 and will be removed in 8.0.0**
+> ([WW-5694](https://issues.apache.org/jira/browse/WW-5694),
+> [WW-5696](https://issues.apache.org/jira/browse/WW-5696)). It only controls the older, generated-JavaScript
+> client-side validator used by the xhtml and css_xhtml themes. It has no effect on the [html5 theme's constraint
+> validation](../core-developers/client-side-validation#html5-constraint-validation), which applications should
+> use instead.
diff --git a/source/tag-developers/xhtml-theme.md b/source/tag-developers/xhtml-theme.md
index feb021489..abed1e85f 100644
--- a/source/tag-developers/xhtml-theme.md
+++ b/source/tag-developers/xhtml-theme.md
@@ -19,8 +19,9 @@ The xhtml provides all the basics that the [simple theme](simple-theme) provides
- Labels for each of the HTML [Struts Tags](struts-tags) on the left hand side (or top, depending on
the `labelposition` attribute)
- [Validation](../core-developers/validation) and error reporting
-- [Pure JavaScript Client Side Validation](../core-developers/pure-java-script-client-side-validation) using
- 100% JavaScript on the browser
+- [Pure JavaScript Client Side Validation](../core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated)
+ using 100% JavaScript on the browser — **deprecated since Struts 7.4.0, removed in 8.0.0**; use the
+ [html5 theme](html5-theme) instead
## Wrapping the Simple Theme
@@ -94,7 +95,8 @@ The head template imports a style sheet. The contents of **styles.css** are:
The xhtml form template sets up the wrapping table around all the other form elements. In addition to creating this
wrapping table, the opening and closing templates also, if the `validate` parameter is set to true, enable
-[Pure JavaScript Client Side Validation](../core-developers/pure-java-script-client-side-validation).
+[Pure JavaScript Client Side Validation](../core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated)
+(deprecated since Struts 7.4.0, removed in 8.0.0).
{% highlight freemarker %}
{% remote_file_content https://raw.githubusercontent.com/apache/struts/main/core/src/main/resources/template/xhtml/form.ftl %}
@@ -110,7 +112,8 @@ The closing template, `form-close.ftl`:
The xhtml form template sets up the wrapping table around all the other [xhtml theme](xhtml-theme) form elements.
In addition to creating this wrapping table, the opening and closing templates also, if the `validate` parameter is set
-to `true`, enable [Pure JavaScript Client Side Validation](../core-developers/pure-java-script-client-side-validation.htmk).
+to `true`, enable [Pure JavaScript Client Side Validation](../core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated)
+(deprecated since Struts 7.4.0, removed in 8.0.0).
See the **form.ftl** contents:
(struts-site) 04/04: docs: fix the stringlength example's direction (server accepts, browser blocks)
Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch docs/html5-constraint-validation
in repository https://gitbox.apache.org/repos/asf/struts-site.git
commit acbface9d4c8e99b72998fadc8b1d5fdb9d197ed
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Tue Aug 25 00:27:39 2026 +0200
docs: fix the stringlength example's direction (server accepts, browser blocks)
The previous sentence said a stringlength validator with maxLength="4" would
reject "abcd " server-side after trimming — backwards. Trimmed to "abcd" (4
chars), StringLengthFieldValidator.validateValue only rejects when
trimmedLength > maxLengthToUse, and 4 > 4 is false, so the server accepts it.
The paragraph exists to show the server-accepts/browser-blocks asymmetry that
makes emitting the constraint attribute risky if trim isn't false; an example
asserting the opposite direction illustrated nothing.
Corrected to state the server accepts "abcd " while a browser maxlength="4"
would stop the fifth character from ever being typed, matching the direction
of the retained [a-z]+/"abc " regex example alongside it.
Co-Authored-By: Claude Opus 5 <no...@anthropic.com>
---
source/core-developers/client-side-validation.md | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/source/core-developers/client-side-validation.md b/source/core-developers/client-side-validation.md
index d81b9c3ea..1bf76e2b4 100644
--- a/source/core-developers/client-side-validation.md
+++ b/source/core-developers/client-side-validation.md
@@ -93,9 +93,10 @@ for the `required` validator on those two types alone.
**Both `minlength`/`maxlength` and `pattern` need `trim="false"`, which is not the default.** Both
`StringLengthFieldValidator.trim` and `RegexFieldValidator.trim` default to `true`, so the server measures
or matches the field's *trimmed* value while the HTML attribute constrains the *raw* one. A `stringlength`
-validator with `maxLength="4"` would reject `"abcd "` server-side after trimming while the browser, seeing
-five raw characters, would block it first — and a `regex` of `[a-z]+` would accept `"abc "` server-side
-while the browser blocks it. Because of this, `minlength`/`maxlength` and `pattern` are only ever emitted
+validator with `maxLength="4"` accepts `"abcd "` — it trims to four characters, which is within the limit —
+but a browser enforcing `maxlength="4"` would stop the user typing the fifth character at all. Likewise, a
+`regex` of `[a-z]+` accepts `"abc "` server-side (it trims to `"abc"` first) while the browser, matching the
+raw value, blocks it. Because of this, `minlength`/`maxlength` and `pattern` are only ever emitted
for validators explicitly configured with `trim="false"` — which most existing `stringlength` and `regex`
validators are not. In practice, expect both to show up rarely until applications start setting
`trim="false"` deliberately for fields where it's safe.