Skip to content

Commit d10560f

Browse files
committed
DATACMNS-1762 - Reintroduce calls to ReactiveWrapperConverters.supports(…) after decoupling from QueryExecutionConverters.
We now consider reactive wrapper types in all areas that previously relied on QueryExecutionConverters to handle reactive type information correctly. Specifically, we call supports(…) and perform type unwrapping to ensure to detect the correct return type.
1 parent af9dd61 commit d10560f

File tree

7 files changed

+31
-11
lines changed

7 files changed

+31
-11
lines changed

src/main/java/org/springframework/data/repository/core/support/AbstractRepositoryMetadata.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,7 @@ public Class<?> getReturnedDomainClass(Method method) {
109109

110110
TypeInformation<?> returnType = getReturnType(method);
111111

112-
if (ReactiveWrapperConverters.supports(returnType.getType())) {
113-
return ReactiveWrapperConverters.unwrapWrapperTypes(returnType).getType();
114-
}
115-
116-
return ReactiveWrapperConverters.unwrapWrapperTypes(QueryExecutionConverters.unwrapWrapperTypes(returnType))
112+
return QueryExecutionConverters.unwrapWrapperTypes(ReactiveWrapperConverters.unwrapWrapperTypes(returnType))
117113
.getType();
118114
}
119115

src/main/java/org/springframework/data/repository/core/support/QueryExecutionResultHandler.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ Object postProcessInvocationResult(@Nullable Object result, int nestingLevel, Re
126126

127127
result = unwrapOptional(result);
128128

129-
if (QueryExecutionConverters.supports(expectedReturnType)) {
129+
if (QueryExecutionConverters.supports(expectedReturnType)
130+
|| ReactiveWrapperConverters.supports(expectedReturnType)) {
130131

131132
// For a wrapper type, try nested resolution first
132133
result = postProcessInvocationResult(result, nestingLevel + 1, descriptor);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ private static boolean isDynamicProjectionParameter(MethodParameter parameter) {
230230
TypeInformation<Object> returnType = ClassTypeInformation.fromReturnTypeOf(method);
231231

232232
return bound
233-
.equals(ReactiveWrapperConverters.unwrapWrapperTypes(QueryExecutionConverters.unwrapWrapperTypes(returnType)));
233+
.equals(QueryExecutionConverters.unwrapWrapperTypes(ReactiveWrapperConverters.unwrapWrapperTypes(returnType)));
234234
}
235235

236236
/**

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.springframework.data.domain.Pageable;
2222
import org.springframework.data.domain.Sort;
2323
import org.springframework.data.repository.util.QueryExecutionConverters;
24+
import org.springframework.data.repository.util.ReactiveWrapperConverters;
2425
import org.springframework.lang.Nullable;
2526
import org.springframework.util.Assert;
2627

@@ -64,7 +65,8 @@ public ParametersParameterAccessor(Parameters<?, ?> parameters, Object[] values)
6465
private static boolean requiresUnwrapping(Object[] values) {
6566

6667
for (Object value : values) {
67-
if (value != null && QueryExecutionConverters.supports(value.getClass())) {
68+
if (value != null && (QueryExecutionConverters.supports(value.getClass())
69+
|| ReactiveWrapperConverters.supports(value.getClass()))) {
6870
return true;
6971
}
7072
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.springframework.data.repository.core.EntityMetadata;
3030
import org.springframework.data.repository.core.RepositoryMetadata;
3131
import org.springframework.data.repository.util.QueryExecutionConverters;
32+
import org.springframework.data.repository.util.ReactiveWrapperConverters;
3233
import org.springframework.data.util.ClassTypeInformation;
3334
import org.springframework.data.util.Lazy;
3435
import org.springframework.data.util.TypeInformation;
@@ -271,7 +272,8 @@ private boolean calculateIsCollectionQuery() {
271272
private static Class<? extends Object> potentiallyUnwrapReturnTypeFor(RepositoryMetadata metadata, Method method) {
272273

273274
TypeInformation<?> returnType = metadata.getReturnType(method);
274-
if (QueryExecutionConverters.supports(returnType.getType())) {
275+
if (QueryExecutionConverters.supports(returnType.getType())
276+
|| ReactiveWrapperConverters.supports(returnType.getType())) {
275277

276278
// unwrap only one level to handle cases like Future<List<Entity>> correctly.
277279

src/main/java/org/springframework/data/repository/util/ClassUtils.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ public static void unwrapReflectionException(Exception ex) throws Throwable {
187187
private static TypeInformation<?> getEffectivelyReturnedTypeFrom(Method method) {
188188

189189
TypeInformation<?> returnType = ClassTypeInformation.fromReturnTypeOf(method);
190-
return QueryExecutionConverters.supports(returnType.getType()) ? returnType.getRequiredComponentType() : returnType;
190+
return QueryExecutionConverters.supports(returnType.getType())
191+
|| ReactiveWrapperConverters.supports(returnType.getType()) ? returnType.getRequiredComponentType()
192+
: returnType;
191193
}
192194
}

src/test/java/org/springframework/data/repository/query/QueryMethodUnitTests.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.stream.Stream;
2929

3030
import org.junit.jupiter.api.Test;
31+
import reactor.core.publisher.Mono;
3132

3233
import org.springframework.data.domain.Page;
3334
import org.springframework.data.domain.Pageable;
@@ -45,6 +46,7 @@
4546
* @author Oliver Gierke
4647
* @author Thomas Darimont
4748
* @author Maciek Opała
49+
* @author Mark Paluch
4850
*/
4951
class QueryMethodUnitTests {
5052

@@ -208,7 +210,7 @@ void detectsWrapperWithinWrapper() throws Exception {
208210
* @see DATACMNS-940
209211
*/
210212
@Test
211-
void detectsSinglValueWrapperWithinWrapper() throws Exception {
213+
void detectsSingleValueWrapperWithinWrapper() throws Exception {
212214

213215
RepositoryMetadata repositoryMetadata = new DefaultRepositoryMetadata(SampleRepository.class);
214216
Method method = SampleRepository.class.getMethod("returnsFutureOfOption");
@@ -234,6 +236,19 @@ void doesNotConsiderMethodForIterableAggregateACollectionQuery() throws Exceptio
234236
assertThat(new QueryMethod(method, metadata, factory).isCollectionQuery()).isFalse();
235237
}
236238

239+
@Test // DATACMNS-1762
240+
void detectsReactiveSliceQuery() throws Exception {
241+
242+
RepositoryMetadata repositoryMetadata = new DefaultRepositoryMetadata(SampleRepository.class);
243+
Method method = SampleRepository.class.getMethod("reactiveSlice");
244+
245+
QueryMethod queryMethod = new QueryMethod(method, repositoryMetadata, factory);
246+
ReturnedType returnedType = queryMethod.getResultProcessor().getReturnedType();
247+
assertThat(queryMethod.isSliceQuery()).isTrue();
248+
assertThat(returnedType.getTypeToRead()).isEqualTo(User.class);
249+
assertThat(returnedType.getDomainType()).isEqualTo(User.class);
250+
}
251+
237252
interface SampleRepository extends Repository<User, Serializable> {
238253

239254
String pagingMethodWithInvalidReturnType(Pageable pageable);
@@ -278,6 +293,8 @@ interface SampleRepository extends Repository<User, Serializable> {
278293
Future<Seq<User>> returnsFutureOfSeq();
279294

280295
Future<Option<User>> returnsFutureOfOption();
296+
297+
Mono<Slice<User>> reactiveSlice();
281298
}
282299

283300
class User {

0 commit comments

Comments
 (0)