DATACMNS-967 - Getters that are default methods are not considered projection input properties anymore.

We now exclude getter methods that are default methods from the consideration which properties of a projection interface are considered input properties in the first place.

Some additional Java 8 polish in DefaultProjectionInformation.
This commit is contained in:
Oliver Gierke
2016-12-23 12:53:36 +01:00
parent 56ec60b269
commit a946d651ff
3 changed files with 50 additions and 18 deletions

View File

@@ -16,9 +16,11 @@
package org.springframework.data.projection;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.BeanUtils;
import org.springframework.util.Assert;
@@ -63,15 +65,9 @@ class DefaultProjectionInformation implements ProjectionInformation {
*/
public List<PropertyDescriptor> getInputProperties() {
List<PropertyDescriptor> result = new ArrayList<PropertyDescriptor>();
for (PropertyDescriptor descriptor : properties) {
if (isInputProperty(descriptor)) {
result.add(descriptor);
}
}
return result;
return properties.stream()//
.filter(it -> isInputProperty(it))//
.collect(Collectors.toList());
}
/*
@@ -104,7 +100,10 @@ class DefaultProjectionInformation implements ProjectionInformation {
private static List<PropertyDescriptor> collectDescriptors(Class<?> type) {
List<PropertyDescriptor> result = new ArrayList<PropertyDescriptor>();
result.addAll(Arrays.asList(BeanUtils.getPropertyDescriptors(type)));
result.addAll(Arrays.stream(BeanUtils.getPropertyDescriptors(type))//
.filter(it -> !hasDefaultGetter(it))//
.collect(Collectors.toList()));
for (Class<?> interfaze : type.getInterfaces()) {
result.addAll(collectDescriptors(interfaze));
@@ -112,4 +111,16 @@ class DefaultProjectionInformation implements ProjectionInformation {
return result;
}
/**
* Returns whether the given {@link PropertyDescriptor} has a getter that is a Java 8 default method.
*
* @param descriptor must not be {@literal null}.
* @return
*/
private static boolean hasDefaultGetter(PropertyDescriptor descriptor) {
Method method = descriptor.getReadMethod();
return method == null ? false : method.isDefault();
}
}

View File

@@ -96,6 +96,10 @@ public class SpelAwareProxyProjectionFactory extends ProxyProjectionFactory impl
@Override
protected boolean isInputProperty(PropertyDescriptor descriptor) {
if (!super.isInputProperty(descriptor)) {
return false;
}
Method readMethod = descriptor.getReadMethod();
if (readMethod == null) {

View File

@@ -19,8 +19,8 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Test;
@@ -53,15 +53,23 @@ public class DefaultProjectionInformationUnitTests {
assertThat(toNames(information.getInputProperties()), hasItems("age", "firstname", "lastname"));
}
/**
* @see DATACMNS-967
*/
@Test
public void doesNotConsiderDefaultMethodInputProperties() throws Exception {
ProjectionInformation information = new DefaultProjectionInformation(WithDefaultMethod.class);
assertThat(information.isClosed(), is(true));
assertThat(toNames(information.getInputProperties()), hasItems("firstname"));
}
private static List<String> toNames(List<PropertyDescriptor> descriptors) {
List<String> names = new ArrayList<String>(descriptors.size());
for (PropertyDescriptor descriptor : descriptors) {
names.add(descriptor.getName());
}
return names;
return descriptors.stream()//
.map(it -> it.getName())//
.collect(Collectors.toList());
}
interface CustomerProjection {
@@ -75,4 +83,13 @@ public class DefaultProjectionInformationUnitTests {
int getAge();
}
interface WithDefaultMethod {
String getFirstname();
default String getLastname() {
return null;
}
}
}