Repository navigation
WW-5811 Derive date min/max and temporal required HTML5 constraints - #2061
Merged
Merged
Conversation
…aints The date control now gets min/max from a range validator whose bounds are LocalDate (localdate) or java.util.Date (date). A Date bound is reduced to its calendar date in the default time zone, the zone the submitted yyyy-MM-dd is parsed in; dropping the time never makes the browser stricter than the server. Years outside 0001-9999 are skipped. A required validator on a temporal control now emits required when the bound property's type converts "" to null (Date and subclasses, Calendar, LocalDate, LocalDateTime, LocalTime, OffsetDateTime), since the empty submit then fails on both sides. A String property keeps "", so it still gets no required. The provider needs the property type for that, so HtmlConstraintProvider gains a default constraintsFor overload carrying it, which delegates to the 7.4.0 method; UIBean calls the new one. Form resolves the type on the object binding writes to (the pushed model, then the action) and walks declared types, so a null intermediate object does not hide it; an indexed or unknown path gives null and no required. month, week, time and datetime-local get no min/max: no built-in converter and range validator pair round-trips their submitted values. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d to end A date validator with XML bounds on a java.util.Date property renders the configured dates under a non-UTC default zone; converting the bound in UTC instead renders 2025-12-31. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Derived constraints can reject server-valid submissions, and date-range dispatch bypasses existing protected overrides.
4 open issues
What changed in this PR
Extends Struts’ HTML5 constraint derivation to temporal controls, using validators and declared property types to generate browser attributes.
Changes:
- Derives date
min/maxbounds and type-aware temporalrequiredattributes. - Adds a property-type-aware provider overload and binding-type lookup.
- Expands provider, property-resolution, and rendering tests.
| File | Description |
|---|---|
| core/src/test/resources/org/apache/struts2/components/ConstraintAction-validation.xml | Adds temporal validation fixtures. |
| core/src/test/java/org/apache/struts2/views/jsp/ui/Html5ConstraintRenderingTest.java | Tests rendered date bounds and required attributes. |
| core/src/test/java/org/apache/struts2/components/StrutsHtmlConstraintProviderTest.java | Covers temporal constraints and provider compatibility. |
| core/src/test/java/org/apache/struts2/components/ConstraintAttributesTest.java | Tests property types passed to providers. |
| core/src/test/java/org/apache/struts2/components/ConstraintAction.java | Adds date and string fixture properties. |
| core/src/main/java/org/apache/struts2/components/UIBean.java | Passes property types to constraint providers. |
| core/src/main/java/org/apache/struts2/components/StrutsHtmlConstraintProvider.java | Implements temporal constraint derivation. |
| core/src/main/java/org/apache/struts2/components/HtmlControlType.java | Adds temporal-control classification. |
| core/src/main/java/org/apache/struts2/components/HtmlConstraintProvider.java | Adds the property-type-aware overload. |
| core/src/main/java/org/apache/struts2/components/Form.java | Resolves declared binding-property types. |
Review effort: Balanced
…e server accepts - The property type is read on the form's submission action class. A different rendering action could declare the same name with another type; a ModelDriven submission action it does not render gives null, as its model type is only known at runtime. - DATE ranges dispatch through addRange again, so a 7.4.0 subclass overriding it keeps receiving them. - A java.util.Date bound before the Gregorian cutover is skipped: DateConverter reads earlier yyyy-MM-dd values as Julian dates, so 1500-01-01 rendered as min="1500-01-10". - A field with its own step gets no derived min, which would become the step base and move the developer's grid. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r S2259 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.




Fixes WW-5811
What changes
HTML5 constraint derivation (
struts.ui.html5.constraints, html5 theme) now covers temporal controls:min/maxondatecontrols from a range validator whose bounds areLocalDate(localdate, WW-5816) orjava.util.Date(date), written asyyyy-MM-dd.java.util.Datebound is reduced to its calendar date in the default time zone, which is the zoneDateConverterparses the submittedyyyy-MM-ddin.minof 10:00 on the 1st, the browser allows the 1st and the server rejects it, which is the permitted direction. Amaxday submits as midnight, which is ≤max.LocalDate.toString()writes+10000-…, which is not a valid HTML date.requiredon temporal controls (date,month,week,time,datetime-local) from arequiredvalidator, when the bound property's declared type converts""to null:java.util.Dateand its subclasses,Calendar,LocalDate,LocalDateTime,LocalTimeandOffsetDateTime.Stringproperty keeps""and so still gets norequired.Design decisions (agreed on the ticket discussion)
datecontrol for ranges. No built-in converter and range validator pair round-trips the other temporal controls:datetime-localsubmits without seconds, whichjava.util.Datedoes not parse.timehas noLocalTimerange validator.monthandweekhave no converter at all.HtmlConstraintProvider(public since 7.4.0) gains adefaultconstraintsFor(..., Class<?> propertyType)overload that delegates to the 7.4.0 method, so existing providers compile and behave unchanged.UIBeancalls the new overload.convertsBlankToNull(Class), so an app whose own converter maps""to a value can override one method.Form.getPropertyTyperesolves the type on the object parameter binding writes to (the pushed model, then the action). It then walks declared types, so a null intermediate object such as a not-yet-createduserdoes not hide it. An indexed or unknown path gives null, which means norequired.addDateRange,addTemporalRequired,convertsBlankToNull), so subclass overrides keep being called.Migration note for 7.5.0
A subclass of
StrutsHtmlConstraintProviderthat overrides the public 4-argumentconstraintsForis now bypassed, because the framework calls the 5-argument overload. Such a subclass should override the 5-argument method instead. Providers that implement the interface directly are unaffected.Tests
StrutsHtmlConstraintProviderTest:LocalDateandjava.util.Datebounds. TheDatecase pinsAsia/Tokyowith a bound whose UTC date differs, so it cannot pass vacuously on a UTC machine.min/max.requiredfor each listed type on each temporal control.requiredforString, for an unknown type, or on a text control.ConstraintAttributesTest: the property type handed to the provider for a top-level field, a nested field through null objects, a model-driven field, and indexed and unknown fields.Html5ConstraintRenderingTest:testRendersNoRequiredOnADateTextField, as the ticket asks.datetextfieldandtextfield type="date"renderingrequired,minandmax, and aString-bound date input rendering norequired.coresuite passes on JDK 17 and JDK 25 (3610 tests).Docs: a struts-site PR follows for
core-developers/client-side-validation.md, whose mapping table still says date ranges are deferred.🤖 Generated with Claude Code