Skip to content

Implement UIViewRoot.restoreViewScopeState() properly - #2212

Merged
BalusC merged 1 commit into
5.0from
mojarra_issue_5787
Jul 16, 2026
Merged

Implement UIViewRoot.restoreViewScopeState() properly#2212
BalusC merged 1 commit into
5.0from
mojarra_issue_5787

Conversation

@BalusC

@BalusC BalusC commented Jul 16, 2026

Copy link
Copy Markdown
Member

Implements UIViewRoot.restoreViewScopeState(FacesContext, Object), a stub since Faces 2.2 (#787). Full rationale in eclipse-ee4j/mojarra#5787; the Mojarra side follows in a separate PR.

The method restored the component tree rather than the view scope and had no callers in Mojarra, so the real behaviour was driven out-of-band through a RESTORE_VIEW_SCOPE_ONLY context attribute. This extracts the view map wiring into a private restoreViewMap(), invokes it from restoreViewScopeState() as StateManagementStrategy.restoreView()'s javadoc prescribes, and drops the attribute branching. The saved state shape is unchanged.

A viewScopeStateRestored flag stops restoreState() from rewiring the view map a second time. That was destructive when the saved view map is no longer among the active view maps (LRU-evicted, or gone with an expired session): building the view mints a replacement, and the second run restored the stale id over it, orphaning it.

Cleaner API/impl split. UIViewRoot is the only class in this repo carrying org.glassfish.mojarra.* string contracts, and it had three. This drops the only one that steered behaviour — restoreState() branched on impl runtime state via a key duplicated as two independent literals with no import between them. The remaining VIEW_MAP_ID_KEY and ACTIVE_VIEW_MAPS_KEY merely name where the view scope data lives; both are tracked by #2185, now the last item for this class.

Compatibility. Public since 2.2 but unused in Mojarra. This makes it load-bearing and corrects its semantics, so any external caller relying on the current behaviour sees a change. The signature is unchanged.

Testing. Full Faces TCK green. Unit tests are added on the Mojarra side, as this repo has no UIViewRoot test; both were verified to fail without this change, and removing only the guard fails only the guard test. Note the TCK pins just the signature — javadoc assertion JSF:JAVADOC:3009 describes this behaviour, is marked testable="true", and has no test.

🤖 Generated with Claude Code (Opus 4.8)

restoreViewScopeState() restored the component tree via
super.restoreState() and never touched the view map id, i.e. the
opposite of what it promises, and had no callers in Mojarra. The view
scope restore was instead driven out-of-band:
FaceletViewHandlingStrategy set a RESTORE_VIEW_SCOPE_ONLY context
attribute and called the full restoreState(), which checked that
attribute to skip super.restoreState() and leave only the view map
wiring.

Extract that wiring into restoreViewMap() and let
restoreViewScopeState() invoke it, so FaceletViewHandlingStrategy can
call the spec method directly, as prescribed by the
StateManagementStrategy.restoreView() javadoc. The saved state shape is
unchanged. This removes the attribute branching along with the
duplicated UIViewRoot.RESTORE_VIEW_SCOPE_ONLY_KEY and
ViewScopeManager.RESTORE_VIEW_SCOPE_ONLY literals.

Guard the wiring with a viewScopeStateRestored flag so restoreState()
skips it once restoreViewScopeState() has run. It previously ran on
both, which is destructive when the saved view map is no longer among
the active view maps -- legitimately LRU-evicted, or gone with an
expired session: building the view mints a replacement via
ViewScopeManager.registerViewMap() and puts its id in the transient
state, and the second run restored the stale id over it and nulled the
view map, orphaning the replacement. Beans created during buildView()
were discarded, @PostConstruct ran again, and the replacement lingered
in the active view maps without ever receiving PreDestroyViewMapEvent.

Ref eclipse-ee4j/mojarra#5787

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@BalusC
BalusC merged commit 321e6fa into 5.0 Jul 16, 2026
2 checks passed
@BalusC
BalusC deleted the mojarra_issue_5787 branch July 16, 2026 12:18
pizzi80 pushed a commit to pizzi80/mojarra that referenced this pull request Jul 16, 2026
Call UIViewRoot.restoreViewScopeState() from the createMetadataView
restore path, as prescribed by the StateManagementStrategy.restoreView()
javadoc, now that jakartaee/faces#2212 implements it properly. This
replaces setting a RESTORE_VIEW_SCOPE_ONLY context attribute around a
full restoreState() call, and lets the ViewScopeManager constant behind
it go.

Add unit tests for both halves of the API change: that
restoreViewScopeState() restores the view map and not the component
state, and that a subsequent restoreState() does not rewire the view map
over a replacement minted while the view was being built. Both fail
without jakartaee/faces#2212.

Bump the faces submodule to 321e6fae1.

Closes eclipse-ee4j#5787

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant