Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8ef195f

Browse files
committed
Introduce BasicPropertyDescriptor to KotlinBeanInfoFactory to bypass early property type validation.
Closes #3167
1 parent f67cb87 commit 8ef195f

File tree

3 files changed

+96
-2
lines changed

3 files changed

+96
-2
lines changed

‎src/main/java/org/springframework/data/util/KotlinBeanInfoFactory.java‎

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.springframework.core.Ordered;
4141
import org.springframework.lang.Nullable;
4242
import org.springframework.util.ClassUtils;
43+
import org.springframework.util.ObjectUtils;
4344
import org.springframework.util.ReflectionUtils;
4445
import org.springframework.util.StringUtils;
4546

@@ -112,8 +113,13 @@ public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
112113

113114
for (PropertyDescriptor descriptor : javaPropertyDescriptors) {
114115

115-
descriptor = new PropertyDescriptor(descriptor.getName(), specialize(beanClass, descriptor.getReadMethod()),
116-
specialize(beanClass, descriptor.getWriteMethod()));
116+
Method getter = specialize(beanClass, descriptor.getReadMethod());
117+
Method setter = specialize(beanClass, descriptor.getWriteMethod());
118+
119+
if (!ObjectUtils.nullSafeEquals(descriptor.getReadMethod(), getter)
120+
|| !ObjectUtils.nullSafeEquals(descriptor.getWriteMethod(), setter)) {
121+
descriptor = new BasicPropertyDescriptor(descriptor.getName(), getter, setter);
122+
}
117123
descriptors.put(descriptor.getName(), descriptor);
118124
}
119125
}
@@ -148,4 +154,44 @@ public int getOrder() {
148154
return LOWEST_PRECEDENCE - 10; // leave some space for customizations.
149155
}
150156

157+
/**
158+
* PropertyDescriptor for {@link KotlinBeanInfoFactory}, not performing any early type determination for
159+
* {@link #setReadMethod}/{@link #setWriteMethod}.
160+
*
161+
* @since 3.3.5
162+
*/
163+
private static class BasicPropertyDescriptor extends PropertyDescriptor {
164+
165+
private @Nullable Method readMethod;
166+
167+
private @Nullable Method writeMethod;
168+
169+
public BasicPropertyDescriptor(String propertyName, @Nullable Method readMethod, @Nullable Method writeMethod)
170+
throws IntrospectionException {
171+
172+
super(propertyName, readMethod, writeMethod);
173+
}
174+
175+
@Override
176+
public void setReadMethod(@Nullable Method readMethod) {
177+
this.readMethod = readMethod;
178+
}
179+
180+
@Override
181+
@Nullable
182+
public Method getReadMethod() {
183+
return this.readMethod;
184+
}
185+
186+
@Override
187+
public void setWriteMethod(@Nullable Method writeMethod) {
188+
this.writeMethod = writeMethod;
189+
}
190+
191+
@Override
192+
@Nullable
193+
public Method getWriteMethod() {
194+
return this.writeMethod;
195+
}
196+
}
151197
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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+
package org.springframework.data.util;
17+
18+
import java.time.LocalDateTime;
19+
import java.time.ZoneId;
20+
import java.util.Date;
21+
import java.util.Optional;
22+
23+
import org.springframework.lang.Nullable;
24+
25+
public abstract class AbstractAuditable {
26+
27+
private @Nullable Date createdDate;
28+
29+
public Optional<LocalDateTime> getCreatedDate() {
30+
return null == createdDate ? Optional.empty() : Optional.of(LocalDateTime.now());
31+
}
32+
33+
public void setCreatedDate(LocalDateTime createdDate) {
34+
this.createdDate = Date.from(createdDate.atZone(ZoneId.systemDefault()).toInstant());
35+
}
36+
37+
}

‎src/test/kotlin/org/springframework/data/util/KotlinBeanInfoFactoryUnitTests.kt‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,13 @@ class KotlinBeanInfoFactoryUnitTests {
130130
)
131131
}
132132

133+
@Test // GH-3167
134+
internal fun supportsPropertiesWithDifferentAccessorTypes() {
135+
136+
val pds = BeanUtils.getPropertyDescriptors(User::class.java)
137+
assertThat(pds).isNotEmpty
138+
}
139+
133140
data class SimpleDataClass(val id: String, var name: String)
134141

135142
@JvmInline
@@ -189,4 +196,8 @@ class KotlinBeanInfoFactoryUnitTests {
189196
return super.getName()
190197
}
191198
}
199+
200+
class User : AbstractAuditable() {
201+
var name: String? = null
202+
}
192203
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /