diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/MethodReference.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/MethodReference.java index 3f7d71bc44..c8fda7f4c6 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/MethodReference.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/MethodReference.java @@ -52,7 +52,14 @@ public class MethodReference extends SpelNodeImpl { TypedValue currentContext = state.getActiveContextObject(); Object[] arguments = new Object[getChildCount()]; for (int i = 0; i < arguments.length; i++) { - arguments[i] = children[i].getValueInternal(state).getValue(); + // Make the root object the active context again for evaluating the parameter + // expressions + try { + state.pushActiveContextObject(state.getRootContextObject()); + arguments[i] = children[i].getValueInternal(state).getValue(); + } finally { + state.popActiveContextObject(); + } } if (currentContext.getValue() == null) { if (nullSafe) { diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java index 61c4676276..6b0a92b47b 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java @@ -367,7 +367,27 @@ public class EvaluationTests extends ExpressionTestCase { public void testTernaryOperatorWithNullValue() { parser.parseExpression("null ? 0 : 1").getValue(); } + + @Test + public void methodCallWithRootReferenceThroughParameter() { + evaluate("placeOfBirth.doubleIt(inventions.length)", 18, Integer.class); + } + + @Test + public void ctorCallWithRootReferenceThroughParameter() { + evaluate("new org.springframework.expression.spel.testresources.PlaceOfBirth(inventions[0].toString()).city", "Telephone repeater", String.class); + } + @Test + public void fnCallWithRootReferenceThroughParameter() { + evaluate("#reverseInt(inventions.length, inventions.length, inventions.length)", "int[3]{9,9,9}", int[].class); + } + + @Test + public void methodCallWithRootReferenceThroughParameterThatIsAFunctionCall() { + evaluate("placeOfBirth.doubleIt(#reverseInt(inventions.length,2,3)[2])", 18, Integer.class); + } + @Test public void testIndexer03() { evaluate("'christian'[8]", "n", String.class); diff --git a/spring-framework-reference/src/expressions.xml b/spring-framework-reference/src/expressions.xml index 041b7bbe3a..34465e071b 100644 --- a/spring-framework-reference/src/expressions.xml +++ b/spring-framework-reference/src/expressions.xml @@ -776,11 +776,13 @@ parser.parseExpression("Name = #newName").getValue(context); System.out.println(tesla.getName()) // "Mike Tesla"
- The #this variable + The #this and #root variables The variable #this is always defined and refers to the current - evaluation object (the object against which unqualified references - will be resolved). + evaluation object (against which unqualified references are resolved). + The variable #root is always defined and refers to the root + context object. Although #this may vary as components of an expression + are evaluated, #root always refers to the root. // create an array of integers List<Integer> primes = new ArrayList<Integer>();