Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In SPEL projection expression, #this as the same value as #root [SPR-13055] #17647

Closed
spring-issuemaster opened this issue May 21, 2015 · 4 comments

Comments

Projects
None yet
2 participants
@spring-issuemaster
Copy link
Collaborator

commented May 21, 2015

Franck MARCHAND opened SPR-13055 and commented

I think #this is not resolved correctly when it is used as an argument of a static method.

If I try to execute this code :


List<Map<String, Object>> myPayload = new ArrayList<Map<String, Object>>();

Map<String, Object> v1 = new HashMap<String, Object>();
Map<String, Object> v2 = new HashMap<String, Object>();

v1.put("test11", "test11");
v1.put("test12", "test12");
v2.put("test21", "test21");
v2.put("test22", "test22");

myPayload.add(v1);
myPayload.add(v2);

EvaluationContext context = new StandardEvaluationContext(myPayload);

ExpressionParser parser=new SpelExpressionParser();

List res = parser.parseExpression("#root.![T(org.springframework.util.StringUtils).collectionToCommaDelimitedString(#this.values())]").getValue(context, List.class);

I get an exception :

org.springframework.expression.spel.SpelEvaluationException: EL1004E:(pos 6): Method call: Method values() cannot be found on java.util.ArrayList type
	at org.springframework.expression.spel.ast.MethodReference.findAccessorForMethod(MethodReference.java:211)
	at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:125)
	at org.springframework.expression.spel.ast.MethodReference.access$000(MethodReference.java:49)
	at org.springframework.expression.spel.ast.MethodReference$MethodValueRef.getValue(MethodReference.java:342)
	at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:88)
	at org.springframework.expression.spel.ast.MethodReference.getArguments(MethodReference.java:154)

In this case #this shouldn't be an ArrayList but a HashMap.

If I don't use #this in the method collectionToCommaDelimitedString, but directly in the projection expression like this :

List res = parser.parseExpression("#root.![#this.values()]").getValue(context, List.class);

I don't have any exceptions and the result is the one I was expecting.


Affects: 4.1.4

Attachments:

Issue Links:

  • #15050 Collection selection and the use of #this
  • #16651 SpEL Collection Selection: "selectionExpression" with method invocation pushes root object as active context instead of current item
@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented May 21, 2015

Andy Clement commented

I will take a look. I think it somewhat relates to #15050 and #16651. Time to tackle this. I think I saw someone hit it on stack overflow again this week too.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented May 21, 2015

Andy Clement commented

Juergen, could you cast an eye over this patch?

With these changes we fix #17647, #15050 and #16651. All variants of the problem of #this (and unqualified) references in projection/selection. I've added test cases for all scenarios and some extra ones (involving maps with projection/selection).

The fix is to do as I mentioned in 12035 - recognize when entering a new scope and remember the object should be used for #this (or for unqualified references) at that nesting level. By remembering it we avoid accidentally using values computed for intermediate computations as we resolve other expression elements at that level. As we exit the scope, we forget the object again.

The downside is, with this fix, some users may find their expressions behave differently if they were relying on the old, wrong, behavior. They could have written something that would work and after this change it will break - to fix it they'd probably need to modify #this references in nested elements of their expressions to #root (or prepend #root to any unqualified references). I think, on balance, it is better to make this change though.

If you are happy with the patch and my comment about affecting existing users, I can push it.

With these fixes I feel I could now tackle SpEL compilation of projection/selection...

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented May 22, 2015

Juergen Hoeller commented

This looks fine to me, Andy. Let's merge it today and roll it into 4.2 RC1 right away!

It should be alright to fix an odd expression here or there in case somebody accidentally used "this" over "root".

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented May 22, 2015

Andy Clement commented

Proposed fix pushed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.