40
40
import org .springframework .graphql .data .method .annotation .support .HandlerDataFetcherExceptionResolver ;
41
41
import org .springframework .graphql .execution .ErrorType ;
42
42
import org .springframework .lang .Nullable ;
43
- import org .springframework .util .Assert ;
44
43
45
44
/**
46
45
* DataFetcher that handles the "_entities" query by invoking
@@ -93,12 +92,11 @@ public Mono<DataFetcherResult<List<Object>>> get(DataFetchingEnvironment env) {
93
92
}
94
93
else {
95
94
if (!batchedTypes .contains (type )) {
96
- EntityBatchDelegate delegate = new EntityBatchDelegate (env , representations , handlerMethod , type );
97
- monoList .add (delegate .invokeEntityBatchMethod ());
95
+ monoList .add (invokeEntitiesMethod (env , handlerMethod , representations , type ));
98
96
batchedTypes .add (type );
99
97
}
100
98
else {
101
- // Covered by batch invocation , but zip needs a value (to be replaced by batch results)
99
+ // Already covered , but zip needs a value (to be replaced by batch results)
102
100
monoList .add (Mono .just (Collections .emptyMap ()));
103
101
}
104
102
}
@@ -107,11 +105,48 @@ public Mono<DataFetcherResult<List<Object>>> get(DataFetchingEnvironment env) {
107
105
}
108
106
109
107
private Mono <Object > invokeEntityMethod (
110
- DataFetchingEnvironment env , EntityHandlerMethod handlerMethod , Map <String , Object > map , int index ) {
108
+ DataFetchingEnvironment environment , EntityHandlerMethod handlerMethod ,
109
+ Map <String , Object > representation , int index ) {
111
110
112
- return handlerMethod .getEntity (env , map )
113
- .switchIfEmpty (Mono .error (new RepresentationNotResolvedException (map , handlerMethod )))
114
- .onErrorResume ((ex ) -> resolveException (ex , env , handlerMethod , index ));
111
+ return handlerMethod .getEntity (environment , representation )
112
+ .switchIfEmpty (Mono .error (new RepresentationNotResolvedException (representation , handlerMethod )))
113
+ .onErrorResume ((ex ) -> resolveException (ex , environment , handlerMethod , index ));
114
+ }
115
+
116
+ private Mono <EntitiesResultContainer > invokeEntitiesMethod (
117
+ DataFetchingEnvironment environment , EntityHandlerMethod handlerMethod ,
118
+ List <Map <String , Object >> representations , String type ) {
119
+
120
+ List <Map <String , Object >> typeRepresentations = new ArrayList <>();
121
+ List <Integer > originalIndexes = new ArrayList <>();
122
+
123
+ for (int i = 0 ; i < representations .size (); i ++) {
124
+ Map <String , Object > map = representations .get (i );
125
+ if (type .equals (map .get ("__typename" ))) {
126
+ typeRepresentations .add (map );
127
+ originalIndexes .add (i );
128
+ }
129
+ }
130
+
131
+ return handlerMethod .getEntities (environment , typeRepresentations )
132
+ .mapNotNull ((result ) -> (((List <?>) result ).isEmpty ()) ? null : result )
133
+ .switchIfEmpty (Mono .defer (() -> {
134
+ List <Mono <?>> exceptions = new ArrayList <>(originalIndexes .size ());
135
+ for (int i = 0 ; i < originalIndexes .size (); i ++) {
136
+ exceptions .add (resolveException (
137
+ new RepresentationNotResolvedException (typeRepresentations .get (i ), handlerMethod ),
138
+ environment , handlerMethod , originalIndexes .get (i )));
139
+ }
140
+ return Mono .zip (exceptions , Arrays ::asList );
141
+ }))
142
+ .onErrorResume ((ex ) -> {
143
+ List <Mono <?>> list = new ArrayList <>();
144
+ for (Integer index : originalIndexes ) {
145
+ list .add (resolveException (ex , environment , handlerMethod , index ));
146
+ }
147
+ return Mono .zip (list , Arrays ::asList );
148
+ })
149
+ .map ((result ) -> new EntitiesResultContainer ((List <?>) result , originalIndexes ));
115
150
}
116
151
117
152
private Mono <ErrorContainer > resolveException (
@@ -141,8 +176,8 @@ private static DataFetcherResult<List<Object>> toDataFetcherResult(List<Object>
141
176
List <GraphQLError > errors = new ArrayList <>();
142
177
for (int i = 0 ; i < entities .size (); i ++) {
143
178
Object entity = entities .get (i );
144
- if (entity instanceof EntityBatchDelegate delegate ) {
145
- delegate . processResults (entities , errors );
179
+ if (entity instanceof EntitiesResultContainer resultHandler ) {
180
+ resultHandler . applyResults (entities , errors );
146
181
}
147
182
if (entity instanceof ErrorContainer errorContainer ) {
148
183
errors .addAll (errorContainer .errors ());
@@ -153,77 +188,6 @@ private static DataFetcherResult<List<Object>> toDataFetcherResult(List<Object>
153
188
}
154
189
155
190
156
- private class EntityBatchDelegate {
157
-
158
- private final DataFetchingEnvironment environment ;
159
-
160
- private final EntityHandlerMethod handlerMethod ;
161
-
162
- private final List <Map <String , Object >> filteredRepresentations = new ArrayList <>();
163
-
164
- private final List <Integer > indexes = new ArrayList <>();
165
-
166
- @ Nullable
167
- private List <?> resultList ;
168
-
169
- EntityBatchDelegate (
170
- DataFetchingEnvironment env , List <Map <String , Object >> allRepresentations ,
171
- EntityHandlerMethod handlerMethod , String type ) {
172
-
173
- this .environment = env ;
174
- this .handlerMethod = handlerMethod ;
175
- for (int i = 0 ; i < allRepresentations .size (); i ++) {
176
- Map <String , Object > map = allRepresentations .get (i );
177
- if (type .equals (map .get ("__typename" ))) {
178
- this .filteredRepresentations .add (map );
179
- this .indexes .add (i );
180
- }
181
- }
182
- }
183
-
184
- Mono <Object > invokeEntityBatchMethod () {
185
- return this .handlerMethod .getEntities (this .environment , this .filteredRepresentations )
186
- .mapNotNull ((result ) -> (((List <?>) result ).isEmpty ()) ? null : result )
187
- .switchIfEmpty (Mono .defer (this ::handleEmptyResult ))
188
- .onErrorResume (this ::handleErrorResult )
189
- .map ((result ) -> {
190
- this .resultList = (List <?>) result ;
191
- return this ;
192
- });
193
- }
194
-
195
- Mono <Object > handleEmptyResult () {
196
- List <Mono <?>> exceptions = new ArrayList <>(this .indexes .size ());
197
- for (int i = 0 ; i < this .indexes .size (); i ++) {
198
- Map <String , Object > map = this .filteredRepresentations .get (i );
199
- Exception ex = new RepresentationNotResolvedException (map , this .handlerMethod );
200
- exceptions .add (resolveException (ex , this .environment , this .handlerMethod , this .indexes .get (i )));
201
- }
202
- return Mono .zip (exceptions , Arrays ::asList );
203
- }
204
-
205
- Mono <List <Object >> handleErrorResult (Throwable ex ) {
206
- List <Mono <?>> list = new ArrayList <>();
207
- for (Integer index : this .indexes ) {
208
- list .add (resolveException (ex , this .environment , this .handlerMethod , index ));
209
- }
210
- return Mono .zip (list , Arrays ::asList );
211
- }
212
-
213
- void processResults (List <Object > entities , List <GraphQLError > errors ) {
214
- Assert .state (this .resultList != null , "Expected resultList" );
215
- for (int i = 0 ; i < this .resultList .size (); i ++) {
216
- Object entity = this .resultList .get (i );
217
- if (entity instanceof ErrorContainer errorContainer ) {
218
- errors .addAll (errorContainer .errors ());
219
- entity = null ;
220
- }
221
- entities .set (this .indexes .get (i ), entity );
222
- }
223
- }
224
- }
225
-
226
-
227
191
private static class IndexedDataFetchingEnvironment extends DelegatingDataFetchingEnvironment {
228
192
229
193
private final ExecutionStepInfo executionStepInfo ;
@@ -242,6 +206,24 @@ public ExecutionStepInfo getExecutionStepInfo() {
242
206
}
243
207
244
208
209
+ private record EntitiesResultContainer (List <?> results , List <Integer > originalIndexes ) {
210
+
211
+ public void applyResults (List <Object > entities , List <GraphQLError > errors ) {
212
+ for (int i = 0 ; i < this .results .size (); i ++) {
213
+ Object result = this .results .get (i );
214
+ Integer index = this .originalIndexes .get (i );
215
+ if (result instanceof ErrorContainer container ) {
216
+ errors .addAll (container .errors ());
217
+ entities .set (index , null );
218
+ }
219
+ else {
220
+ entities .set (index , result );
221
+ }
222
+ }
223
+ }
224
+ }
225
+
226
+
245
227
private record ErrorContainer (List <GraphQLError > errors ) {
246
228
247
229
ErrorContainer (GraphQLError error ) {
0 commit comments