Skip to content

Commit 52e10da

Browse files
committed
Consider projections without input properties open ones.
Closes #3164
1 parent a13f75e commit 52e10da

File tree

4 files changed

+47
-1
lines changed

4 files changed

+47
-1
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public List<PropertyDescriptor> getInputProperties() {
8282

8383
@Override
8484
public boolean isClosed() {
85-
return this.properties.equals(getInputProperties());
85+
return hasInputProperties() && this.properties.equals(getInputProperties());
8686
}
8787

8888
/**

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import java.beans.PropertyDescriptor;
1919
import java.util.List;
2020

21+
import org.springframework.util.CollectionUtils;
22+
2123
/**
2224
* Information about a projection type.
2325
*
@@ -40,6 +42,17 @@ public interface ProjectionInformation {
4042
*/
4143
List<PropertyDescriptor> getInputProperties();
4244

45+
/**
46+
* Returns whether the projection has input properties. Projections without input types are typically open projections
47+
* that do not follow Java's property accessor naming.
48+
*
49+
* @return
50+
* @since 3.2.11
51+
*/
52+
default boolean hasInputProperties() {
53+
return !CollectionUtils.isEmpty(getInputProperties());
54+
}
55+
4356
/**
4457
* Returns whether supplying values for the properties returned via {@link #getInputProperties()} is sufficient to
4558
* create a working proxy instance. This will usually be used to determine whether the projection uses any dynamically

src/main/java/org/springframework/data/repository/query/ReturnedType.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.springframework.lang.Nullable;
3434
import org.springframework.util.Assert;
3535
import org.springframework.util.ClassUtils;
36+
import org.springframework.util.CollectionUtils;
3637
import org.springframework.util.ConcurrentReferenceHashMap;
3738
import org.springframework.util.ObjectUtils;
3839

@@ -129,9 +130,21 @@ public final boolean isInstance(@Nullable Object source) {
129130
* Returns the properties required to be used to populate the result.
130131
*
131132
* @return
133+
* @see ProjectionInformation#getInputProperties()
132134
*/
133135
public abstract List<String> getInputProperties();
134136

137+
/**
138+
* Returns whether the returned type has input properties.
139+
*
140+
* @return
141+
* @since 3.2.11
142+
* @see ProjectionInformation#hasInputProperties()
143+
*/
144+
public boolean hasInputProperties() {
145+
return !CollectionUtils.isEmpty(getInputProperties());
146+
}
147+
135148
/**
136149
* A {@link ReturnedType} that's backed by an interface.
137150
*

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.springframework.aop.Advisor;
3232
import org.springframework.aop.TargetClassAware;
3333
import org.springframework.aop.framework.Advised;
34+
import org.springframework.beans.factory.annotation.Value;
3435
import org.springframework.test.util.ReflectionTestUtils;
3536

3637
/**
@@ -135,6 +136,19 @@ void returnsAllPropertiesAsInputProperties() {
135136
var result = projectionInformation.getInputProperties();
136137

137138
assertThat(result).hasSize(6);
139+
assertThat(projectionInformation.hasInputProperties()).isTrue();
140+
assertThat(projectionInformation.isClosed()).isTrue();
141+
}
142+
143+
@Test // DATACMNS-630
144+
void identifiersOpenProjectionCorrectly() {
145+
146+
var projectionInformation = factory.getProjectionInformation(OpenProjection.class);
147+
var result = projectionInformation.getInputProperties();
148+
149+
assertThat(result).isEmpty();
150+
assertThat(projectionInformation.hasInputProperties()).isFalse();
151+
assertThat(projectionInformation.isClosed()).isFalse();
138152
}
139153

140154
@Test // DATACMNS-655, GH-2831
@@ -357,6 +371,12 @@ interface CustomerExcerpt {
357371
Map<String, Object> getData();
358372
}
359373

374+
interface OpenProjection {
375+
376+
@Value("#{@greetingsFrom.groot(target.firstname)}")
377+
String hello();
378+
}
379+
360380
interface CustomerExcerptWithDefaultMethod extends CustomerExcerpt {
361381

362382
default String getFirstnameAndId() {

0 commit comments

Comments
 (0)