Skip to content

Compiled SpEL expression is bound to first evaluated argument type instead of declared parameter type for method and constructor invocations #34245

@TigerZCoder

Description

@TigerZCoder

When using methods with interface/superclass parameters, SpEL will compile with the first actual argument and narrow the argument type, then fail on the other implementations.
The following unit test will reproduce the problem:

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import org.junit.jupiter.api.Test;

import org.springframework.expression.Expression;
import org.springframework.expression.spel.SpelCompilerMode;
import org.springframework.expression.spel.SpelParserConfiguration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.ReflectionUtils;

class Tests {

	@Test
	void invocationOnInterfaceParameter() {
		StandardEvaluationContext context = new StandardEvaluationContext();
		// register a function which accept a parameter of interface/superclass
		context.setVariable("reverseList", ReflectionUtils.findMethod(Collections.class, "reverse", List.class));
		// use immediate compilation mode to compile the expression
		SpelExpressionParser immediateCompileParser = new SpelExpressionParser(new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null));
		// parse the expression
		Expression expression = immediateCompileParser.parseExpression("#reverseList(#root)");
		// evaluate the expression twice to trigger the compilation use one of the implementation
		expression.getValue(context, new LinkedList<>());
		expression.getValue(context, new LinkedList<>());
		// evaluate the expression with the other implementation
		expression.getValue(context, new ArrayList<>());
	}

}

I think

should pass the requiredTypeDesc in and cast to this type, or do not cast at ?
I don't know the underlying implementation of SpEL, I'm just describing what I saw.

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)status: declinedA suggestion or change that we don't feel we should currently apply

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions