Skip to content

Commit

Permalink
Introduce BasicPropertyDescriptor to KotlinBeanInfoFactory to byp…
Browse files Browse the repository at this point in the history
…ass early property type validation.

Closes #3167
  • Loading branch information
mp911de committed Sep 30, 2024
1 parent 4645ac3 commit 4ada6b9
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.springframework.core.Ordered;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

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

for (PropertyDescriptor descriptor : javaPropertyDescriptors) {

descriptor = new PropertyDescriptor(descriptor.getName(), specialize(beanClass, descriptor.getReadMethod()),
specialize(beanClass, descriptor.getWriteMethod()));
Method getter = specialize(beanClass, descriptor.getReadMethod());
Method setter = specialize(beanClass, descriptor.getWriteMethod());

if (!ObjectUtils.nullSafeEquals(descriptor.getReadMethod(), getter)
|| !ObjectUtils.nullSafeEquals(descriptor.getWriteMethod(), setter)) {
descriptor = new BasicPropertyDescriptor(descriptor.getName(), getter, setter);
}
descriptors.put(descriptor.getName(), descriptor);
}
}
Expand Down Expand Up @@ -148,4 +154,44 @@ public int getOrder() {
return LOWEST_PRECEDENCE - 10; // leave some space for customizations.
}

/**
* PropertyDescriptor for {@link KotlinBeanInfoFactory}, not performing any early type determination for
* {@link #setReadMethod}/{@link #setWriteMethod}.
*
* @since 3.3.5
*/
private static class BasicPropertyDescriptor extends PropertyDescriptor {

private @Nullable Method readMethod;

private @Nullable Method writeMethod;

public BasicPropertyDescriptor(String propertyName, @Nullable Method readMethod, @Nullable Method writeMethod)
throws IntrospectionException {

super(propertyName, readMethod, writeMethod);
}

@Override
public void setReadMethod(@Nullable Method readMethod) {
this.readMethod = readMethod;
}

@Override
@Nullable
public Method getReadMethod() {
return this.readMethod;
}

@Override
public void setWriteMethod(@Nullable Method writeMethod) {
this.writeMethod = writeMethod;
}

@Override
@Nullable
public Method getWriteMethod() {
return this.writeMethod;
}
}
}
37 changes: 37 additions & 0 deletions src/test/java/org/springframework/data/util/AbstractAuditable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.util;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Optional;

import org.springframework.lang.Nullable;

public abstract class AbstractAuditable {

private @Nullable Date createdDate;

public Optional<LocalDateTime> getCreatedDate() {
return null == createdDate ? Optional.empty() : Optional.of(LocalDateTime.now());
}

public void setCreatedDate(LocalDateTime createdDate) {
this.createdDate = Date.from(createdDate.atZone(ZoneId.systemDefault()).toInstant());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@ class KotlinBeanInfoFactoryUnitTests {
)
}

@Test // GH-3167
internal fun supportsPropertiesWithDifferentAccessorTypes() {

val pds = BeanUtils.getPropertyDescriptors(User::class.java)
assertThat(pds).isNotEmpty
}

data class SimpleDataClass(val id: String, var name: String)

@JvmInline
Expand Down Expand Up @@ -189,4 +196,8 @@ class KotlinBeanInfoFactoryUnitTests {
return super.getName()
}
}

class User : AbstractAuditable() {
var name: String? = null
}
}

0 comments on commit 4ada6b9

Please sign in to comment.