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
@@ -54,25 +56,59 @@ abstract class RepositoryMethodInvoker {
54
56
private final Class <?> returnedType ;
55
57
private final Invokable invokable ;
56
58
private final boolean suspendedDeclaredMethod ;
57
- private final boolean returnsReactiveType ;
58
59
59
60
protected RepositoryMethodInvoker (Method method , Invokable invokable ) {
60
61
61
62
this .method = method ;
62
- this .invokable = invokable ;
63
63
64
64
if (KotlinDetector .isKotlinReflectPresent ()) {
65
65
66
66
this .suspendedDeclaredMethod = KotlinReflectionUtils .isSuspend (method );
67
67
this .returnedType = this .suspendedDeclaredMethod ? KotlinReflectionUtils .getReturnType (method )
68
68
: method .getReturnType ();
69
+
70
+ // special case for most query methods: These can return Flux but we don't want to fail later on if the method
71
+ // is void.
72
+ if (suspendedDeclaredMethod ) {
73
+
74
+ this .invokable = args -> {
75
+
76
+ Object result = invokable .invoke (args );
77
+
78
+ if (returnedType == Unit .class ) {
79
+
80
+ if (result instanceof Mono <?> m ) {
81
+ return m .then ();
82
+ }
83
+
84
+ if (result instanceof Flux <?> f ) {
85
+ return f .then ();
86
+ }
87
+
88
+ return ReactiveWrapperConverters .toWrapper (result , Flux .class ).then ();
89
+ }
90
+
91
+ if (returnedType != Flow .class ) {
92
+
93
+ if (result instanceof Mono <?> m ) {
94
+ return m ;
95
+ }
96
+
97
+ return ReactiveWrapperConverters .toWrapper (result , Flux .class ).singleOrEmpty ();
98
+ }
99
+
100
+ return result ;
101
+ };
102
+ } else {
103
+ this .invokable = invokable ;
104
+ }
105
+
69
106
} else {
70
107
71
108
this .suspendedDeclaredMethod = false ;
72
109
this .returnedType = method .getReturnType ();
110
+ this .invokable = invokable ;
73
111
}
74
-
75
- this .returnsReactiveType = ReactiveWrappers .supports (returnedType );
76
112
}
77
113
78
114
static RepositoryQueryMethodInvoker forRepositoryQuery (Method declaredMethod , RepositoryQuery query ) {
@@ -154,7 +190,7 @@ private RepositoryMethodInvocation computeInvocationResult(RepositoryMethodInvoc
154
190
interface Invokable {
155
191
156
192
@ Nullable
157
- Object invoke (Object [] args ) throws ReflectiveOperationException ;
193
+ Object invoke (Object [] args ) throws Exception ;
158
194
}
159
195
160
196
/**
@@ -214,8 +250,6 @@ Publisher<Object> decorate(Class<?> repositoryInterface, RepositoryInvocationMul
214
250
*/
215
251
private static class RepositoryFragmentMethodInvoker extends RepositoryMethodInvoker {
216
252
217
- private final CoroutineAdapterInformation adapterInformation ;
218
-
219
253
public RepositoryFragmentMethodInvoker (Method declaredMethod , Object instance , Method baseClassMethod ) {
220
254
this (CoroutineAdapterInformation .create (declaredMethod , baseClassMethod ), declaredMethod , instance ,
221
255
baseClassMethod );
@@ -236,13 +270,12 @@ public RepositoryFragmentMethodInvoker(CoroutineAdapterInformation adapterInform
236
270
return AopUtils .invokeJoinpointUsingReflection (instance , baseClassMethod , invocationArguments );
237
271
}
238
272
return AopUtils .invokeJoinpointUsingReflection (instance , baseClassMethod , args );
239
- } catch (RuntimeException e ) {
273
+ } catch (Exception e ) {
240
274
throw e ;
241
275
} catch (Throwable e ) {
242
276
throw new RuntimeException (e );
243
277
}
244
278
});
245
- this .adapterInformation = adapterInformation ;
246
279
}
247
280
248
281
/**
0 commit comments