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

Support varargs invocations in SpEL for varargs array subtype #32704

Closed
wants to merge 1 commit into from

Conversation

LeMikaelF
Copy link
Contributor

@LeMikaelF LeMikaelF commented Apr 25, 2024

There was a bug in SpEL where an array passed into a varargs method could be wrapped one too many times if the component type of the argument didn't match the component type of the parameter. For example:

@Test
void givenArrayFromVariable_whenInvokeVarargsMethod_thenCorrectArguments() {
	ExpressionParser parser = new SpelExpressionParser();
	StandardEvaluationContext context = new StandardEvaluationContext();
	Recorder recorder = new Recorder();
	context.setVariable("recorder", recorder);
	context.setVariable("myArray", new String[] { "a", "b" });

	parser.parseExpression("#recorder.record(#myArray)").getValue(context);

	assertThat(recorder.getArgs()).asInstanceOf(ARRAY).containsExactly("a", "b");
}

private static class Recorder {
	@Nullable private Object[] args;

        // test would pass with (String... args)
	public void record(Object... args) {
		this.args = args;
	}
	
	@Nullable
	public Object[] getArgs() {
		return args;
	}
}

This fails with the following error message:

Expecting actual:
  [["a", "b"]]
to contain exactly (and in same order):
  ["a", "b"]

I've added more exhaustive test cases for the method where the bug was, as well as a test in SpelCompilationCoverageTests. I've added this last test just next to another test that was commented out with a TODO, and had to comment out part of my test because of the same bug, but fixing this exposes another underlying bug that I've fixed in another branch, and I was able to uncomment the tests that were commented out. The fix is ready, I'm just waiting for this one to be merged.

I may also have accidentally uncovered another bug in SpEL. At line 4651 in SpelCompilationCoverageTests, the method seventeen() isn't actually invoked with (), yet it's still executed and its result value is available. I'm not sure this is desirable behaviour.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Apr 25, 2024
@jhoeller jhoeller requested a review from sbrannen April 25, 2024 09:14
@sbrannen sbrannen changed the title Fix array wrapping in varargs invocations. Fix array wrapping for varargs invocations in SpEL Apr 25, 2024
@sbrannen

This comment was marked as outdated.

@sbrannen sbrannen added status: waiting-for-feedback We need additional information before we can continue in: core Issues in core modules (aop, beans, core, context, expression) and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Apr 25, 2024
@LeMikaelF

This comment was marked as outdated.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Apr 25, 2024
@dcollins123
Copy link

dcollins123 commented May 1, 2024

Could you add * before the array var so the elements become individual args?

parser.parseExpression("#recorder.record(*#myArray)").getValue(context);

@sbrannen
Copy link
Member

sbrannen commented May 3, 2024

I may also have accidentally uncovered another bug in SpEL. At line 4651 in SpelCompilationCoverageTests, the method seventeen() isn't actually invoked with (), yet it's still executed and its result value is available. I'm not sure this is desirable behaviour.

That's to be expected: when seventeen is encountered in that expression without (), it is treated as a property reference that resolves to the seventeen() method in the root context object.

@sbrannen
Copy link
Member

sbrannen commented May 3, 2024

I've added this last test just next to another test that was commented out with a TODO, and had to comment out part of my test because of the same bug, but fixing this exposes another underlying bug that I've fixed in another branch, and I was able to uncomment the tests that were commented out. The fix is ready, I'm just waiting for this one to be merged.

Do you mean that you have a second fix for which you plan to submit a PR that will address the following TODO regarding compilation of varargs method invocations?

// TODO Determine why the String[] is passed as the first element of the Object... varargs array instead of the entire varargs array.

@sbrannen
Copy link
Member

sbrannen commented May 3, 2024

Could you add * before the array var so the elements become individual args?

@dcollins123, * is not proper syntax for a SpEL expression.

@sbrannen sbrannen self-assigned this May 3, 2024
@sbrannen sbrannen added type: enhancement A general enhancement and removed status: feedback-provided Feedback has been provided labels May 3, 2024
@sbrannen sbrannen added this to the 6.1.7 milestone May 3, 2024
@sbrannen sbrannen changed the title Fix array wrapping for varargs invocations in SpEL Support varargs invocations in SpEL for varargs array subtype May 3, 2024
@sbrannen
Copy link
Member

sbrannen commented May 3, 2024

There was a bug in SpEL where an array passed into a varargs method could be wrapped one too many times if the component type of the argument didn't match the component type of the parameter.

SpEL has supported varargs invocations for methods and constructors for quite a while with the limitation that the supplied array must match the declared varargs type.

In light of that, we consider this an "enhancement" rather than a "bug", and we will include this in the upcoming 6.1.7. release.

Copy link
Member

@sbrannen sbrannen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the raising the issue, the PR itself, and for the additional tests for var-args invocations.

I left a few comments which I will address locally before merging.

sbrannen added a commit to sbrannen/spring-framework that referenced this pull request May 3, 2024
sbrannen added a commit that referenced this pull request May 3, 2024
@sbrannen sbrannen closed this in f51be0a May 3, 2024
@LeMikaelF
Copy link
Contributor Author

Do you mean that you have a second fix for which you plan to submit a PR that will address the following TODO regarding compilation of varargs method invocations?

Yes, exactly.

@sbrannen
Copy link
Member

sbrannen commented May 4, 2024

Do you mean that you have a second fix for which you plan to submit a PR that will address the following TODO regarding compilation of varargs method invocations?

Yes, exactly.

@LeMikaelF, that would be great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants