Skip to content

SpEL PropertyAccessor ordering for supertype and generic matches does not adhere to contract #33861

Closed
@sbrannen

Description

@sbrannen

Overview

The PropertyAccessor SPI in the Spring Expression Language (SpEL) defines a getSpecificTargetClasses() method which allows an accessor to declare what types the accessor supports, or null if it is a "generic" accessor.

The contract for ordering accessors is only partially mentioned in the Javadoc for PropertyAccessor; however, it is explained in detail in the Javadoc for org.springframework.expression.spel.ast.AstUtils.getPropertyAccessorsToTry():

The resolvers are considered to be in an ordered list, however in the returned list any that are exact matches for the input target type (as opposed to 'general' resolvers that could work for any type) are placed at the start of the list. In addition, there are specific resolvers that exactly name the class in question and resolvers that name a specific class but it is a supertype of the class we have. These are put at the end of the specific resolvers set and will be tried after exactly matching accessors but before generic accessors.

And similar Javadoc exists for the private getPropertyAccessorsToTry() method in PropertyOrFieldReference.

However, the implementations of AstUtils.getPropertyAccessorsToTry() and PropertyOrFieldReference.getPropertyAccessorsToTry() do not honor that last part of the contract.

On the contrary, a generic accessor (such as ReflectivePropertyAccessor) is ordered before a custom PropertyAccessor that claims to support a supertype of the target type, if the generic accessor is registered before the custom accessor.

In other words, a generic accessor can incorrectly take priority over a matching type-specific accessor.

Deliverables

  • Ensure that property accessors are ordered so that type-matching accessors always have a higher priority than generic/fallback accessors.
  • Ensure that property accessors are evaluated in the order in which they were registered.
  • Fix the algorithm in AstUtils.getPropertyAccessorsToTry() and remove the duplicate algorithm in PropertyOrFieldReference.getPropertyAccessorsToTry().
  • Introduce tests for AstUtils.getPropertyAccessorsToTry() in 6.1.x and main.

Related Issues

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions