Skip to content

Commit ac09de8

Browse files
christophstroblmp911de
authored andcommitted
Fix property lookup for projections on Kotlin types.
This commit makes sure to use the target objects method to determine the property used for the projection. Closes: #3127 Original pull request: #3129
1 parent 3b48160 commit ac09de8

File tree

3 files changed

+44
-3
lines changed

3 files changed

+44
-3
lines changed

src/main/java/org/springframework/data/projection/PropertyAccessingMethodInterceptor.java

+11-3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
* @author Oliver Gierke
3434
* @author Mark Paluch
3535
* @author Johannes Englmeier
36+
* @author Christoph Strobl
3637
* @since 1.10
3738
*/
3839
class PropertyAccessingMethodInterceptor implements MethodInterceptor {
@@ -54,12 +55,11 @@ public PropertyAccessingMethodInterceptor(Object target) {
5455
@Override
5556
public Object invoke(@SuppressWarnings("null") MethodInvocation invocation) throws Throwable {
5657

57-
Method method = invocation.getMethod();
58-
59-
if (ReflectionUtils.isObjectMethod(method)) {
58+
if (ReflectionUtils.isObjectMethod(invocation.getMethod())) {
6059
return invocation.proceed();
6160
}
6261

62+
Method method = lookupTargetMethod(invocation, target.getWrappedClass());
6363
PropertyDescriptor descriptor = BeanUtils.findPropertyForMethod(method);
6464

6565
if (descriptor == null) {
@@ -81,4 +81,12 @@ public Object invoke(@SuppressWarnings("null") MethodInvocation invocation) thro
8181
private static boolean isSetterMethod(Method method, PropertyDescriptor descriptor) {
8282
return method.equals(descriptor.getWriteMethod());
8383
}
84+
85+
private static Method lookupTargetMethod(MethodInvocation invocation, Class<?> targetType) {
86+
87+
Method method = BeanUtils.findMethod(targetType, invocation.getMethod().getName(),
88+
invocation.getMethod().getParameterTypes());
89+
90+
return method != null ? method : invocation.getMethod();
91+
}
8492
}

src/test/java/org/springframework/data/projection/PropertyAccessingMethodInterceptorUnitTests.java

+10
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
*
3333
* @author Oliver Gierke
3434
* @author Mark Paluch
35+
* @author Christoph Strobl
3536
*/
3637
@ExtendWith(MockitoExtension.class)
3738
class PropertyAccessingMethodInterceptorUnitTests {
@@ -111,6 +112,15 @@ void throwsAppropriateExceptionIfThePropertyCannotWritten() throws Throwable {
111112
.isThrownBy(() -> new PropertyAccessingMethodInterceptor(new Source()).invoke(invocation));
112113
}
113114

115+
@Test // GH-3127
116+
void detectsKotlinPropertiesWithLeadingIsOnTargetType() throws Throwable {
117+
118+
var source = new WithIsNamedProperty(true);
119+
when(invocation.getMethod()).thenReturn(WithIsNamedPropertyProjection.class.getMethod("isValid"));
120+
121+
assertThat(new PropertyAccessingMethodInterceptor(source).invoke(invocation)).isEqualTo(true);
122+
}
123+
114124
static class Source {
115125

116126
String firstname;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.data.projection
18+
19+
interface WithIsNamedPropertyProjection {
20+
val isValid: Boolean
21+
}
22+
23+
class WithIsNamedProperty(val isValid : Boolean)

0 commit comments

Comments
 (0)