Fix #5885: index tag ids through implicit facet panels on refresh - #5886
Merged
Conversation
buildTagIdIndex descended into an IMPLICIT_PANEL only for panels among the children, not among the facets, while a facet is the only place Facelets ever creates one: addComponent wraps a facet that receives a second child. So on a refresh-time re-apply every component inside a multi-child facet missed the index and was recreated, dropping its per-request state — an input lost its submitted value and its invalid state and re-rendered the model value next to its validation message. The index generation now also counts the children of the implicit panels it indexed through, so a body that adds one under an otherwise unchanged parent still invalidates the entry. TCK coverage in jakartaee/faces#2218. Co-Authored-By: Claude Opus 5 (1M context) <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.
What
Closes #5885: a
UIInputinside an<f:facet>with more than one child lost its submitted value and its invalid state during Render Response, so a failed ajax validation re-rendered the model value next to the error message.ComponentSupport.buildTagIdIndexdescended into anIMPLICIT_PANELonly for panels sitting among the parent's children, not among its facets — while a facet is the only place Facelets ever creates one (addComponentwraps a facet that receives a second child). The scan it replaced,findChildByTagIdFullStateSaving, lumps facets and children into one list and therefore covers both. So on a refresh-time re-apply every component inside a multi-child facet missed the index, was treated as new, and was recreated;markForDeletion/finalizeForDeletionthen dropped the original along with its per-request state. TheFacesMessagesurvived because it lives inFacesContextkeyed by client id, hence an error message next to a field that looks valid.The two conditions in the report follow from this: a single-child facet is the facet, so the
facetNamefast path finds it; and the render-time re-apply only runs at all when the view carries a dynamic action (canSkipTransientBuildRefresh), which is why a programmatically added component resource was needed to expose it.Both loops now index through implicit panels, and the index generation additionally counts the children of the panels it indexed through, so a body that adds a component under an otherwise unchanged parent still invalidates the entry.
Regression from #5835 (4.0.20 / 4.1.11 / 5.0). The report bisected to 4.1.10, which contains both #5835 and the render-refresh skip (#5815) that gates when the defect is observable.
Not limited to
UIInput: any per-request component state inside a multi-child facet was lost on that re-apply.Testing
New TCK IT in jakartaee/faces#2218 (
faces50/facelets,Issue5885IT), run against this branch's master equivalent:testSingleChildFacettestMultiChildFacetexpected: <> but was: <MODEL VALUE>The implicit panel is specified behaviour: the
f:facetVDLDoc has said since 2.3 that "When the facet contains more than one child the children will be automatically put in a container UIPanel". The older prose in Standard Tag Libraries, "Using Facets" — "one and only one child UIComponent tag", with footnote 10 pointing at<h:panelGroup>— predates that and was never reconciled with it. Wrapping the children in an<h:panelGroup>is nevertheless a working workaround on an affected release, since the facet then has a single child.Full Jakarta Faces TCK passes. 4.1 and master upmerge to follow.
🤖 Generated with Claude Code (Opus 5)