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

Collection selection and the use of #this [SPR-10417] #15050

Closed
spring-issuemaster opened this issue Mar 25, 2013 · 3 comments

Comments

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

commented Mar 25, 2013

Ram Chidambaram opened SPR-10417 and commented

I have 2 lists containing strings and i would like to check if an item in one list is contained in another. I tried this using the Collection selection.

list1 contains values "a", "b", "x"
list 2 contains values "c", "x"

#list1.?\[#list2.contains(#this)\]

The expected result is a list with "x". But I just get an empty result.

I'm expecting the #this inside the collection selection would point to the current iteration item. Is this not the case ?


Affects: 3.1.2

Issue Links:

  • #16651 SpEL Collection Selection: "selectionExpression" with method invocation pushes root object as active context instead of current item
  • #17647 In SPEL projection expression, #this as the same value as #root

0 votes, 5 watchers

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 27, 2013

Phil Webb commented

It seems that the #this object is always reset to the root object during method calls, see the org.springframework.expression.spel.ast.MethodReference getValueRef method:

// 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();
}

This means that #self does reference the iterator item but unfortunately not during the call to .contains().

Have you considered writing a custom function that could return the intersection of the two lists? Something like:

public void SPR_10417() throws Exception {
	StandardEvaluationContext context = new StandardEvaluationContext();
	context.registerFunction("intersect",
		getClass().getDeclaredMethod("intersect", Collection.class, Collection.class));

	Expression exp = parser.parseExpression("#intersect(#list1, #list2)");
	List<String> list1 = new ArrayList<String>(Arrays.asList("a", "b", "c"));
	List<String> list2 = new ArrayList<String>(Arrays.asList("c", "x"));
	context.setVariable("list1", list1);
	context.setVariable("list2", list2);
	Object value = exp.getValue(context);
	System.out.println(value);
}

public static List intersect(Collection a, Collection b) {
	List list = new ArrayList(a);
	list.retainAll(b);
	return list;
}
@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Oct 27, 2014

Andy Clement commented

This is somewhat related to #16651, under that bug I might make some changes, they just need to be done carefully and with an eye on what impact it will have to existing users.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented May 22, 2015

Andy Clement commented

Fixed by commit for #17647. Test cases based on this issue included.

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.