You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@struts.apache.org by "Lukasz Lenart (Jira)" <ji...@apache.org> on 2026/09/13 19:43:00 UTC

[jira] [Created] (WW-5740) Resolve HTML5 constraint messages for visitor-validated fields against the visited object

Lukasz Lenart created WW-5740:
---------------------------------

             Summary: Resolve HTML5 constraint messages for visitor-validated fields against the visited object
                 Key: WW-5740
                 URL: https://issues.apache.org/jira/browse/WW-5740
             Project: Struts 2
          Issue Type: Improvement
          Components: Core Tags
            Reporter: Lukasz Lenart
             Fix For: 7.4.0


Follow-up to WW-5702 item 4, found in review of its PR.

{{Form.getFieldValidators}} now unwraps {{FieldVisitorValidatorWrapper}}, so a field such as {{user.name}} behind a {{visitor}} validator on {{user}} gets its concrete constraint and a {{data-msg-requiredstring}} message. The message text, however, is resolved by {{StrutsHtmlConstraintProvider.addMessage}} via {{validator.getMessage(action)}}, which builds a {{DelegatingValidatorContext}} over the *action's* bundles only.

Server-side, {{VisitorFieldValidator.validateObject}} validates with {{createTextProvider(visited, parent)}} — a {{CompositeTextProvider}} that also consults the *visited object's* bundle, and pushes the visited object onto the stack first. So for the usual reusable-model pattern:
* {{ConstraintUser-validation.xml}} declares {{<message key="name.required"/>}}
* the text lives in {{ConstraintUser.properties}}

validation shows the localized text while the rendered field carries {{data-msg-requiredstring="name.required"}} — {{ValidatorSupport.getMessage}} falls back to the raw key. A {{${...}}} in the nested message that refers to a property of the visited bean resolves against the action for the same reason.

This predates WW-5702 (the wrapper already delegated {{getMessage(action)}}), but it used to land under the useless {{data-msg-field-visitor}} name; now it lands under the real validator type and looks correct.

Fixing it means the provider needs the object each validator ran against, not only the action:
* {{Form}} carries the visitor prefix out of {{findFieldValidators}} (or returns validator + prefix pairs)
* {{UIBean.addConstraintAttributes}} resolves the visited bean from the stack by that prefix
* {{HtmlConstraintProvider.constraintsFor}} receives it — an interface change, acceptable while 7.4.0 is unreleased
* {{addMessage}} resolves through the same composite text provider validation uses, with the action as fallback

Test: a {{<message key=.../>}} in the visited class's own validation file, with the text in the visited class's {{.properties}}; assert the rendered {{data-msg-*}} carries the text, not the key.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)