Fix context root preservation during nested evaluations#449
Merged
lukaszlenart merged 2 commits intomainfrom Oct 25, 2025
Merged
Fix context root preservation during nested evaluations#449lukaszlenart merged 2 commits intomainfrom
lukaszlenart merged 2 commits intomainfrom
Conversation
Fixes issue where addDefaultContext() unconditionally overwrites the context root, breaking expressions that reference #root during list processing operations (selection, projection, etc.). The fix preserves the original root when: - Context exists with a non-null root - Context has user-defined variables (size() > 0) - A different root is being set (nested evaluation) This allows #root to correctly reference the original context object during list operations while still supporting legitimate context reuse with different roots (when size() == 0). Note: context.size() only counts user-defined variables, not built-in reserved keys like #root, #this, and _traceEvaluations. Fixes #390
Adds test cases covering various scenarios where context root should be preserved during nested evaluations: - List selection with #root references - List projection with #root references - Lambda expressions accessing #root - Context variable access during list processing - Verification that root is not overwritten by list items These tests ensure issue #390 is properly resolved and prevent regression in future changes. Related to #390
|
lukaszlenart
added a commit
that referenced
this pull request
Oct 25, 2025
…uilder This commit resolves the conflict between the generic context feature and PR #449 (fix/context-root-preservation-issue-390) by integrating the root preservation logic into the OgnlContext.Builder provider. The root preservation logic from PR #449 prevented context root overwriting during nested evaluations (like list processing). When the generic context branch replaced addDefaultContext() with a builder pattern, this logic was lost during the rebase. This fix adds the same conditional logic to the builder's default provider: - Checks if initialContext is an OgnlContext instance - Preserves original root when context has user variables (size() > 0) - Preserves original root when new root differs from existing root - Otherwise uses the new root (normal behavior) All 607 tests pass, including the 8 context root preservation tests from PR #449. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
lukaszlenart
added a commit
that referenced
this pull request
Oct 25, 2025
…uilder This commit resolves the conflict between the generic context feature and PR #449 (fix/context-root-preservation-issue-390) by integrating the root preservation logic into the OgnlContext.Builder provider. The root preservation logic from PR #449 prevented context root overwriting during nested evaluations (like list processing). When the generic context branch replaced addDefaultContext() with a builder pattern, this logic was lost during the rebase. This fix adds the same conditional logic to the builder's default provider: - Checks if initialContext is an OgnlContext instance - Preserves original root when context has user variables (size() > 0) - Preserves original root when new root differs from existing root - Otherwise uses the new root (normal behavior) All 607 tests pass, including the 8 context root preservation tests from PR #449. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Merged
lukaszlenart
added a commit
that referenced
this pull request
Oct 25, 2025
…uilder This commit resolves the conflict between the generic context feature and PR #449 (fix/context-root-preservation-issue-390) by integrating the root preservation logic into the OgnlContext.Builder provider. The root preservation logic from PR #449 prevented context root overwriting during nested evaluations (like list processing). When the generic context branch replaced addDefaultContext() with a builder pattern, this logic was lost during the rebase. This fix adds the same conditional logic to the builder's default provider: - Checks if initialContext is an OgnlContext instance - Preserves original root when context has user variables (size() > 0) - Preserves original root when new root differs from existing root - Otherwise uses the new root (normal behavior) All 607 tests pass, including the 8 context root preservation tests from PR #449. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This was referenced Oct 26, 2025
lukaszlenart
added a commit
that referenced
this pull request
Oct 26, 2025
Port changes from #449 about root preservation
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.


Summary
Fixes #390 - Context root overwriting breaks expressions that reference
#rootduring list processing operations.Problem
PR #337 introduced a change to
addDefaultContext()that unconditionally overwrites the context root withresult.setRoot(root). This breaks functionality when:OgnlContextwith a root object#root.propertygetValue()is called with each list item as therootparameteraddDefaultContext()overwrites the original context root with the list item#rootnow incorrectly points to the list item instead of the original context rootExample failure:
Solution
Preserve the original context root during nested evaluations by detecting when:
initialContextexists with a non-null rootinitialContexthas user-defined variables (size() > 0)rootis being set (nested evaluation scenario)When all conditions are met, preserve the original root. Otherwise, use default behavior.
Key insight:
context.size()only counts user-defined variables, not reserved keys like#root,#this,_traceEvaluations. This allows us to distinguish between:size() == 0): Update root (supports existing use cases)size() > 0): Preserve root (fixes issue ognl 3.4.5 - context root is overwritten on getValue() #390)Changes
ognl/src/main/java/ognl/Ognl.java: UpdatedaddDefaultContext()with conditional logic to preserve context root during nested evaluationsognl/src/test/java/ognl/test/ContextRootPreservationTest.java: Added 8 comprehensive test cases covering:#rootreferences#rootreferences#rootTest Results
✅ All 607 tests pass (including 8 new tests)
Backward Compatibility
The fix maintains full backward compatibility:
size() == 0)size() > 0)Related Issues