spring-projects / spring-framework

Spring Framework
https://spring.io/projects/spring-framework
Apache License 2.0
56.62k stars 38.13k forks source link

SpEL expression on a reloadable type can no longer be resolved #31668

Closed kzander91 closed 11 months ago

kzander91 commented 11 months ago

Starting with Boot 3.1.6/Framework 6.0.14, the following SpEL expression fails to resolve the referenced type, but only when devtools is on the classpath: T(com.example.MyEnum).VALUE The following exception is thrown:

Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:118)
        at java.base/java.lang.reflect.Method.invoke(Method.java:580)
        at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50)
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1005E: Type cannot be found 'com.example.demo.MyEnum'
        at org.springframework.expression.spel.support.StandardTypeLocator.findType(StandardTypeLocator.java:128)
        at org.springframework.expression.spel.ExpressionState.findType(ExpressionState.java:180)
        at org.springframework.expression.spel.ast.TypeReference.getValueInternal(TypeReference.java:70)
        at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:61)
        at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:97)
        at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:114)
        at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:142)
        at com.example.demo.DemoApplication.main(DemoApplication.java:15)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
        ... 2 more

Downgrading to Framework 6.0.13, or removing devtools fixes it.

Reproducer: demo.zip

Main:

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);

        System.out.println(new SpelExpressionParser()
                .parseExpression("T(com.example.demo.MyEnum).VALUE")
                .getValue());
    }

}

MyEnum.java:

public enum MyEnum {
    VALUE
}

Extract and run ./mvnw spring-boot:run, the exception occurs. Open the pom.xml and change the Spring Framework version to 6.0.13, run again and the code succeeds. Alternatively, leave the Spring Framework version as is and remove the devtools dependency instead, run again and the code succeeds as well.

Maybe related: #31579

jhoeller commented 11 months ago

Ouch that's an oversight in the StandardTypeLocator cache handling where we mean to not cache if the class is reloadable, but the code path actually not just bypasses the cache, it also bypasses the return statement... Sorry for the glitch, we'll fix this ASAP.