Skip to content

SpEL: static access via the type function fails if the class implements Map [SPR-9861] #14494

@spring-projects-issues

Description

@spring-projects-issues

Sam Brannen opened SPR-9861 and commented

Status Quo

When using SpEL's type function T to access a static constant, evaluation of the expression fails if the class referenced by the T function implements java.util.Map.

For example, the following SpEL expression (taken from an excerpt from a project using Spring Integration) fails:

<header name="#{T(org.springframework.integration.MessageHeaders).CORRELATION_ID}" value="foo" />

... with the following exception:

Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to java.util.Map 
        at org.springframework.context.expression.MapAccessor.canRead(MapAccessor.java:37) 
        at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:190)

        at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:72)

        at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:57) 
        at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:93) 
        at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:88) 
        at org.springframework.context.expression.StandardBeanExpressionResolver.evaluate(StandardBeanExpressionResolver.java:139)

        ... 47 more

Analysis

The reason for the above exception is that Spring Integration's MessageHeaders class implements java.util.Map. Thus the SpEL MapAccessor is added to the list of candidate property accessors to try in PropertyOrFieldReference.getPropertyAccessorsToTry(Class<?>, ExpressionState), and MapAccessor ends up in the candidate list before ReflectivePropertyAccessor.

So, when the expression is evaluated, it fails since the T() function returns a class instead of a Map instance. In other words, the MapAccessor assumes it is being passed an instance of java.util.Map, when it in fact receives an instance of java.lang.Class (i.e., the class reference returned by the T() function).

In summary, MapAccessor obviously cannot be used to access static members. Thus the current implementation is completely broken in that the building of the candidate property accessor list does not take into account that the eventual property access may be static.


Deliverables

  1. Ensure that static members (i.e., constants) can be accessed in SpEL expressions using the T() function when the class passed to the T() function implements java.util.Map.

Affects: 3.0 GA

Issue Links:

Backported to: 3.2.9

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)status: backportedAn issue that has been backported to maintenance branchesstatus: duplicateA duplicate of another issue

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions