15
15
*/
16
16
package org .springframework .data .repository .core .support ;
17
17
18
+ import kotlin .Unit ;
18
19
import kotlin .reflect .KFunction ;
20
+ import kotlinx .coroutines .flow .Flow ;
19
21
import reactor .core .publisher .Flux ;
20
22
import reactor .core .publisher .Mono ;
21
23
22
24
import java .lang .reflect .InvocationTargetException ;
23
25
import java .lang .reflect .Method ;
26
+ import java .util .Collection ;
24
27
import java .util .stream .Stream ;
25
28
26
29
import org .reactivestreams .Publisher ;
@@ -54,25 +57,63 @@ abstract class RepositoryMethodInvoker {
54
57
private final Class <?> returnedType ;
55
58
private final Invokable invokable ;
56
59
private final boolean suspendedDeclaredMethod ;
57
- private final boolean returnsReactiveType ;
58
60
61
+ @ SuppressWarnings ("ReactiveStreamsUnusedPublisher" )
59
62
protected RepositoryMethodInvoker (Method method , Invokable invokable ) {
60
63
61
64
this .method = method ;
62
- this .invokable = invokable ;
63
65
64
66
if (KotlinDetector .isKotlinReflectPresent ()) {
65
67
66
68
this .suspendedDeclaredMethod = KotlinReflectionUtils .isSuspend (method );
67
69
this .returnedType = this .suspendedDeclaredMethod ? KotlinReflectionUtils .getReturnType (method )
68
70
: method .getReturnType ();
71
+
72
+ // special case for most query methods: These can return Flux but we don't want to fail later on if the method
73
+ // is void.
74
+ if (suspendedDeclaredMethod ) {
75
+
76
+ this .invokable = args -> {
77
+
78
+ Object result = invokable .invoke (args );
79
+
80
+ if (returnedType == Unit .class ) {
81
+
82
+ if (result instanceof Mono <?> m ) {
83
+ return m .then ();
84
+ }
85
+
86
+ Flux <?> flux = result instanceof Flux <?> f ? f : ReactiveWrapperConverters .toWrapper (result , Flux .class );
87
+ return flux .then ();
88
+ }
89
+
90
+ if (returnedType != Flow .class ) {
91
+
92
+ if (result instanceof Mono <?> m ) {
93
+ return m ;
94
+ }
95
+
96
+ Flux <?> flux = result instanceof Flux <?> f ? f : ReactiveWrapperConverters .toWrapper (result , Flux .class );
97
+
98
+ if (Collection .class .isAssignableFrom (returnedType )) {
99
+ return flux .collectList ();
100
+ }
101
+
102
+ return flux .singleOrEmpty ();
103
+ }
104
+
105
+ return result ;
106
+ };
107
+ } else {
108
+ this .invokable = invokable ;
109
+ }
110
+
69
111
} else {
70
112
71
113
this .suspendedDeclaredMethod = false ;
72
114
this .returnedType = method .getReturnType ();
115
+ this .invokable = invokable ;
73
116
}
74
-
75
- this .returnsReactiveType = ReactiveWrappers .supports (returnedType );
76
117
}
77
118
78
119
static RepositoryQueryMethodInvoker forRepositoryQuery (Method declaredMethod , RepositoryQuery query ) {
@@ -154,7 +195,7 @@ private RepositoryMethodInvocation computeInvocationResult(RepositoryMethodInvoc
154
195
interface Invokable {
155
196
156
197
@ Nullable
157
- Object invoke (Object [] args ) throws ReflectiveOperationException ;
198
+ Object invoke (Object [] args ) throws Exception ;
158
199
}
159
200
160
201
/**
@@ -214,8 +255,6 @@ Publisher<Object> decorate(Class<?> repositoryInterface, RepositoryInvocationMul
214
255
*/
215
256
private static class RepositoryFragmentMethodInvoker extends RepositoryMethodInvoker {
216
257
217
- private final CoroutineAdapterInformation adapterInformation ;
218
-
219
258
public RepositoryFragmentMethodInvoker (Method declaredMethod , Object instance , Method baseClassMethod ) {
220
259
this (CoroutineAdapterInformation .create (declaredMethod , baseClassMethod ), declaredMethod , instance ,
221
260
baseClassMethod );
@@ -236,13 +275,12 @@ public RepositoryFragmentMethodInvoker(CoroutineAdapterInformation adapterInform
236
275
return AopUtils .invokeJoinpointUsingReflection (instance , baseClassMethod , invocationArguments );
237
276
}
238
277
return AopUtils .invokeJoinpointUsingReflection (instance , baseClassMethod , args );
239
- } catch (RuntimeException e ) {
278
+ } catch (Exception e ) {
240
279
throw e ;
241
280
} catch (Throwable e ) {
242
281
throw new RuntimeException (e );
243
282
}
244
283
});
245
- this .adapterInformation = adapterInformation ;
246
284
}
247
285
248
286
/**
0 commit comments