From 83667f808cf7c7e57f74efc884fb13dead7040a3 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Mon, 4 May 2026 18:41:17 +0200 Subject: [PATCH] Ensure getters have non-void return types in SpEL Closes gh-36800 --- .../spel/support/ReflectivePropertyAccessor.java | 8 ++++++-- .../expression/spel/PropertyAccessTests.java | 12 ++++++++++++ .../expression/spel/testresources/Person.java | 4 ++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java b/spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java index 06f93226093..b9e2fcbd077 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java @@ -374,10 +374,11 @@ public class ReflectivePropertyAccessor implements PropertyAccessor { * Find a getter method for the specified property. */ protected @Nullable Method findGetterForProperty(String propertyName, Class clazz, boolean mustBeStatic) { - Method method = findMethodForProperty(getPropertyMethodSuffixes(propertyName), + String[] methodSuffixes = getPropertyMethodSuffixes(propertyName); + Method method = findMethodForProperty(methodSuffixes, "get", clazz, mustBeStatic, 0, ANY_TYPES); if (method == null) { - method = findMethodForProperty(getPropertyMethodSuffixes(propertyName), + method = findMethodForProperty(methodSuffixes, "is", clazz, mustBeStatic, 0, BOOLEAN_TYPES); if (method == null) { // Record-style plain accessor method, for example, name() @@ -385,6 +386,9 @@ public class ReflectivePropertyAccessor implements PropertyAccessor { "", clazz, mustBeStatic, 0, ANY_TYPES); } } + if (method != null && method.getReturnType() == void.class) { + method = null; // not a valid accessor method + } return method; } diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/PropertyAccessTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/PropertyAccessTests.java index a5ab11cbb51..2209f56cd09 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/PropertyAccessTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/PropertyAccessTests.java @@ -16,6 +16,7 @@ package org.springframework.expression.spel; +import java.lang.reflect.Method; import java.time.ZoneId; import java.util.ArrayList; import java.util.Collections; @@ -39,6 +40,7 @@ import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.expression.spel.testresources.Inventor; import org.springframework.expression.spel.testresources.Person; import org.springframework.expression.spel.testresources.RecordPerson; +import org.springframework.util.ClassUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -202,6 +204,16 @@ class PropertyAccessTests extends AbstractExpressionTests { target.setName("p2"); assertThat(expr.getValue(context, target)).isEqualTo("p2"); + assertThatSpelEvaluationException() + .isThrownBy(() -> parser.parseExpression("nonexistent").getValue(context, target)) + .extracting(SpelEvaluationException::getMessageCode).isEqualTo(SpelMessage.PROPERTY_OR_FIELD_NOT_READABLE); + + Method getInvalid = ClassUtils.getMethod(Person.class, "getInvalid"); + assertThat(getInvalid.getReturnType()).isEqualTo(void.class); + assertThatSpelEvaluationException() + .isThrownBy(() -> parser.parseExpression("invalid").getValue(context, target)) + .extracting(SpelEvaluationException::getMessageCode).isEqualTo(SpelMessage.PROPERTY_OR_FIELD_NOT_READABLE); + assertThatSpelEvaluationException() .isThrownBy(() -> parser.parseExpression("name='p3'").getValue(context, target)) .extracting(SpelEvaluationException::getMessageCode).isEqualTo(SpelMessage.NOT_ASSIGNABLE); diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/testresources/Person.java b/spring-expression/src/test/java/org/springframework/expression/spel/testresources/Person.java index 017bef65612..8237f9f33d8 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/testresources/Person.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/testresources/Person.java @@ -59,4 +59,8 @@ public class Person { return company; } + public void getInvalid() { + // no-op + } + }