-
Notifications
You must be signed in to change notification settings - Fork 38.7k
Description
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
- Ensure that static members (i.e., constants) can be accessed in SpEL expressions using the
T()
function when the class passed to theT()
function implementsjava.util.Map
.
Affects: 3.0 GA
Issue Links:
- Referencing static field of class that extends Map in expression language causes class cast exception [SPR-11609] #16232 Referencing static field of class that extends Map in expression language causes class cast exception ("duplicates")
Backported to: 3.2.9