lukaszlenart opened a new pull request, #1865:
URL: https://github.com/apache/struts/pull/1865

   Adds HTML5 constraint validation to the `html5` theme, and deprecates the 
generated-JavaScript
   client-side validator it replaces.
   
   Fixes [WW-5695](https://issues.apache.org/jira/browse/WW-5695)
   Fixes [WW-5694](https://issues.apache.org/jira/browse/WW-5694)
   
   Supersedes [WW-2975](https://issues.apache.org/jira/browse/WW-2975) (closed 
Won't Fix), open since 2009.
   Removal of the JavaScript validator is tracked separately as
   [WW-5696](https://issues.apache.org/jira/browse/WW-5696) and is **not** in 
this PR.
   
   ## Why
   
   `xhtml/form-close-validate.ftl` builds its `validateForm_<id>()` function 
from the form's `tagNames`
   list, which is populated only when a UI tag finds the form via 
`findAncestor(Form.class)`. Any input
   reaching the markup another way — raw HTML, a custom tag, an included 
fragment — is silently
   unvalidated. That is WW-2975, and it still reproduced on `main`.
   
   Rather than patch that list, this replaces the mechanism. Constraints now 
ride on each `<input>`, so
   there is no central field list for a field to be missing from — the root 
cause disappears instead of
   being worked around.
   
   ## The governing rule: never false-reject
   
   A constraint is emitted **only** when the browser cannot reject input the 
server would have accepted.
   A browser rejecting what the server allows leaves the user with a form that 
will not submit and no
   explanation. Being conservative merely costs a field its client-side check, 
which is harmless.
   
   The main consequence: **Struts never sets or changes an input's `type`.** 
Promoting a field to
   `type="number"` would reject `1234,50`, which locale-aware conversion 
accepts in a comma-decimal
   locale, and the browsers' `email`/`url` grammars differ from 
`EmailValidator`/`URLValidator`.
   
   ## What is emitted
   
   | Validator | Emits | Condition |
   |---|---|---|
   | `requiredstring` | `required` | text-entry controls and `textarea` |
   | `required` | `required` | only `radio` and `file` |
   | `stringlength` | `minlength` / `maxlength` | text-entry or `textarea`, and 
`trim="false"` |
   | `regex` | `pattern` | text-entry, `caseSensitive="true"`, `trim="false"`, 
ECMAScript-safe, not email/creditcard |
   | `int`, `short`, `long`, `double` | `min` / `max` | only when the control 
is already `type="number"`/`range`; `min` only when integral |
   | `date` | — | temporal formatting deferred |
   | `email`, `url`, `creditcard` | — | never |
   | any validator with a message | `data-msg-<type>` | always, including those 
emitting no constraint |
   
   Struts ships **no JavaScript** consuming `data-msg-*`; they carry the 
resolved i18n message for an
   application's own script.
   
   Three conditions are worth knowing because they limit reach:
   
   - `required` is split because `RequiredFieldValidator` only fails on 
null/empty-array/empty-collection.
     `CheckboxInterceptor` substitutes `"false"` for an unticked box, so the 
server accepts what a browser
     `required` would block. Only `radio` and `file` omit the parameter 
entirely when empty.
   - `minlength`/`maxlength` and `pattern` both need `trim="false"`, which is 
**not** the default — the
     server measures/matches the trimmed value while the attribute constrains 
the raw one. Expect both to
     be uncommon until applications opt in.
   - `\s`/`\S` are excluded from the ECMAScript-safe allowlist: Java's is 
ASCII-only by default while
     ECMAScript's is the wider Unicode set, so `^\S+$` would accept a value 
containing NBSP server-side
     and reject it in the browser.
   
   ## Compatibility
   
   Off by default (`struts.ui.html5.constraints=false`), so nothing renders 
differently on upgrade — the
   `html5` theme shipped in 7.2.0 and existing forms are untouched. The 
deprecation is annotations and
   documentation only; all four `validateForm_` golden files are byte-identical.
   
   The mapping policy is a swappable bean (`HtmlConstraintProvider`, under 
`struts.htmlConstraintProvider`)
   for applications wanting a less conservative mapping.
   
   ## Testing
   
   Full core suite: **3257 tests, 0 failures.** `mvn apache-rat:check` clean. 
The plugin modules that
   consume `UIBean` (`javatemplates`, `velocity`) verified green with `-am`.
   
   Several tests exist specifically to be able to fail: the hook-ordering test 
was confirmed to fail when
   the hook is moved, the memoisation test when the cache is disabled, and the 
byte-exact disabled-path
   test when the template regresses — the shared golden-file harness normalises 
whitespace away, so it
   cannot catch that class of defect on its own.
   
   ## Known follow-ups
   
   - The `trim` guard over-restricts `minlength`: browser-reject implies 
server-reject there, so it could
     safely be emitted even when trimming. Widening it is a follow-up.
   - Temporal `min`/`max` needs per-control ISO formatting.
   - The `try/catch` guarding derivation has no regression test yet.
   
   Documentation is a companion change in `struts-site`.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to