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 <[email protected]>
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 <[email protected]>
---
 .../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:
 

Reply via email to