fix: treat HierarchicalDataProvider.refreshItem(null) as virtual root - #25100
fix: treat HierarchicalDataProvider.refreshItem(null) as virtual root#25100arimu1 wants to merge 6 commits into
Conversation
182a45e to
36738ba
Compare
|
Re-triggered CI after CLA was signed. Local verification (JBR 17):
Null item is treated as the virtual hierarchy root → |
|
Fixed TeamCity Formatter failures: Spotless javadoc line wraps in |
| rootCache.clear(); | ||
| rootCache.setSize(getDataProviderChildCount(null)); | ||
| requestFlush().invalidateViewport(); |
There was a problem hiding this comment.
With refreshChildren = true, the behavior seems to be equivalent to calling reset().
With refreshChildren = false, something feels a bit off to me: we are explicitly asking not to refresh the children, yet the virtual root's children get refreshed, while refreshItem(item, false) with a non-null item leaves them untouched. If the behavior doesn't follow the flag either way, maybe differentiating on it just adds confusion? Always calling refreshAll might be simpler and more consistent. @arimu1 do you have a use case that would require these two to behave differently?
| T rootItem = rootCache.getItem(i); | ||
| keyMapper.refresh(rootItem); | ||
| dataGenerator.refreshData(rootItem); |
There was a problem hiding this comment.
Does this actually accomplish anything? Refreshing an item with the same cached reference looks like a no-op to me.
| T rootItem = rootCache.getItem(i); | ||
| keyMapper.refresh(rootItem); | ||
| dataGenerator.refreshData(rootItem); | ||
| requestFlush().invalidateItem(rootItem); |
There was a problem hiding this comment.
So this effectively just resends to the client the generated data of the root items within the viewport. What scenario needs that? Maybe exposing refreshViewport would be a better fit?
|
@vursen Thanks for the review — simplified per your suggestions. A. Simplified: B. Same-reference in-place refresh C. Root viewport resend / NPE fix retained: Local: |
|
Follow-up after TeamCity red + local investigation: Local Locally now:
Also rebased onto current |
f05157e to
510ad78
Compare
null is the virtual root (parent of root-level items) in TreeData-style hierarchies. Calling refreshItem(null) previously threw NPE in DataRefreshEvent. Allow null in DataRefreshEvent for hierarchical virtual-root semantics. refreshItem(null) refreshes root-level items only; refreshItem(null, true) re-fetches root children via HierarchicalDataCommunicator without a full reset()/refreshAll() (acknowledging that equating null to refreshAll is too broad). Fixes vaadin#19377
TeamCity Formatter failed on javadoc line wrapping in DataChangeEvent and HierarchicalDataCommunicator. spotless:apply only; behavior unchanged.
Per maintainer review (@vursen): differentiating refreshChildren for the virtual root was inconsistent with non-null item semantics and the same-reference in-place path was effectively a no-op. Null is the virtual hierarchy root (call sites use refreshItem(getParent(item), true) for roots → null). Always map it to refreshAll()/reset() regardless of refreshChildren. Keep DataRefreshEvent allowing null so the NPE from vaadin#19377 stays fixed.
reset() preserves expand state; after refresh(null) with Item 0 expanded and a new root, flattened size is 4 not 3. Aligns with refreshAll behavior.
510ad78 to
1816aec
Compare
|
Rebased onto latest |
|
Hi @vursen — following up on the TeamCity failures. After the last rebase + force-push, all five TeamCity jobs (Formatter / Gradle Tests / API-DIFF labeling / Validation / Validation-SlowTests) are still red simultaneously. I tried to read the TeamCity logs but they require authentication (no guest access succeeded). Locally I verified the minimal change set against The spotless plugin is configured to enforce Could you share the TeamCity log (or confirm whether this is a known infra issue for fork-based PRs)? Happy to adjust if there is a real finding — I just cannot see past the auth wall. |
Description
HierarchicalDataProvider.refreshItem(null)threw aNullPointerExceptionbecauseDataRefreshEventrequired a non-null item.In hierarchical data models such as
TreeData,nullis the virtual root (the parent of root-level items). Call sites that dorefreshItem(getParent(item), true)therefore hit NPE when the item is a root.Semantics (simplified after review)
Per @vursen and the original expectation on #19377:
refreshItem(null)is equivalent torefreshAll()/ communicatorreset(), regardless ofrefreshChildren. Differentiating on that flag for the virtual root was inconsistent with non-null item semantics; the same-reference in-place path was a no-op and was removed.DataRefreshEventstill allowsnullso the hierarchical virtual-root path does not throw.Changes
DataChangeEvent.DataRefreshEvent: allownullitem (virtual root)AbstractHierarchicalDataProvider:refreshItem(null[, *])→refreshAll()HierarchicalDataCommunicator.refresh(null, *)→reset()Fixes #19377
Local verification
mvn -pl flow-data -Dtest=HierarchicalDataCommunicatorDataRefreshTest test— 19/19 (JDK 21)mvn -pl flow-data spotless:check— clean