@@ -110,106 +110,75 @@ public Mono<Object> resolveArgument(
110
110
parameter .getGenericParameterType ());
111
111
112
112
String name = ModelInitializer .getNameForParameter (parameter );
113
- Mono <?> valueMono = prepareAttributeMono (name , valueType , context , exchange );
113
+ Mono <?> attributeMono = prepareAttributeMono (name , valueType , context , exchange );
114
114
115
115
// unsafe(): we're intercepting, already serialized Publisher signals
116
116
Sinks .One <BindingResult > bindingResultSink = Sinks .unsafe ().one ();
117
117
118
118
Map <String , Object > model = context .getModel ().asMap ();
119
119
model .put (BindingResult .MODEL_KEY_PREFIX + name , bindingResultSink .asMono ());
120
120
121
- return valueMono .flatMap (value -> {
122
- WebExchangeDataBinder binder = context .createDataBinder (exchange , value , name , parameter );
123
- return (bindingDisabled (parameter ) ? Mono . empty () : bindRequestParameters (binder , exchange ))
121
+ return attributeMono .flatMap (attribute -> {
122
+ WebExchangeDataBinder binder = context .createDataBinder (exchange , attribute , name , parameter );
123
+ return (! bindingDisabled (parameter ) ? bindRequestParameters (binder , exchange ) : Mono . empty ( ))
124
124
.doOnError (bindingResultSink ::tryEmitError )
125
125
.doOnSuccess (aVoid -> {
126
126
validateIfApplicable (binder , parameter , exchange );
127
127
BindingResult bindingResult = binder .getBindingResult ();
128
128
model .put (BindingResult .MODEL_KEY_PREFIX + name , bindingResult );
129
- model .put (name , value );
129
+ model .put (name , attribute );
130
130
// Ignore result: serialized and buffered (should never fail)
131
131
bindingResultSink .tryEmitValue (bindingResult );
132
132
})
133
133
.then (Mono .fromCallable (() -> {
134
134
BindingResult errors = binder .getBindingResult ();
135
135
if (adapter != null ) {
136
136
return adapter .fromPublisher (errors .hasErrors () ?
137
- Mono .error (new WebExchangeBindException (parameter , errors )) : valueMono );
137
+ Mono .error (new WebExchangeBindException (parameter , errors )) : attributeMono );
138
138
}
139
139
else {
140
140
if (errors .hasErrors () && !hasErrorsArgument (parameter )) {
141
141
throw new WebExchangeBindException (parameter , errors );
142
142
}
143
- return value ;
143
+ return attribute ;
144
144
}
145
145
}));
146
146
});
147
147
}
148
148
149
- /**
150
- * Determine if binding should be disabled for the supplied {@link MethodParameter},
151
- * based on the {@link ModelAttribute#binding} annotation attribute.
152
- * @since 5.2.15
153
- */
154
- private boolean bindingDisabled (MethodParameter parameter ) {
155
- ModelAttribute modelAttribute = parameter .getParameterAnnotation (ModelAttribute .class );
156
- return (modelAttribute != null && !modelAttribute .binding ());
157
- }
158
-
159
- /**
160
- * Extension point to bind the request to the target object.
161
- * @param binder the data binder instance to use for the binding
162
- * @param exchange the current request
163
- * @since 5.2.6
164
- */
165
- protected Mono <Void > bindRequestParameters (WebExchangeDataBinder binder , ServerWebExchange exchange ) {
166
- return binder .bind (exchange );
167
- }
168
-
169
- private Mono <?> prepareAttributeMono (String attributeName , ResolvableType attributeType ,
170
- BindingContext context , ServerWebExchange exchange ) {
149
+ private Mono <?> prepareAttributeMono (
150
+ String name , ResolvableType type , BindingContext context , ServerWebExchange exchange ) {
171
151
172
- Object attribute = context .getModel ().asMap ().get (attributeName );
152
+ Object attribute = context .getModel ().asMap ().get (name );
173
153
174
154
if (attribute == null ) {
175
- attribute = findAndRemoveReactiveAttribute (context .getModel (), attributeName );
155
+ attribute = removeReactiveAttribute (context .getModel (), name );
176
156
}
177
157
178
158
if (attribute == null ) {
179
- return createAttribute (attributeName , attributeType .toClass (), context , exchange );
159
+ return createAttribute (name , type .toClass (), context , exchange );
180
160
}
181
161
182
162
ReactiveAdapter adapter = getAdapterRegistry ().getAdapter (null , attribute );
183
- if (adapter != null ) {
184
- Assert .isTrue (!adapter .isMultiValue (), "Data binding only supports single-value async types" );
185
- return Mono .from (adapter .toPublisher (attribute ));
186
- }
187
- else {
188
- return Mono .justOrEmpty (attribute );
189
- }
163
+ Assert .isTrue (adapter == null || !adapter .isMultiValue (), "Model attribute must be single-value publisher" );
164
+ return (adapter != null ? Mono .from (adapter .toPublisher (attribute )) : Mono .justOrEmpty (attribute ));
190
165
}
191
166
192
167
@ Nullable
193
- private Object findAndRemoveReactiveAttribute (Model model , String attributeName ) {
194
- return model .asMap ().entrySet (). stream ()
195
- . filter (entry -> {
196
- if (! entry . getKey (). startsWith ( attributeName )) {
197
- return false ;
198
- }
199
- ReactiveAdapter adapter = getAdapterRegistry (). getAdapter ( null , entry . getValue ());
200
- if ( adapter == null ) {
201
- return false ;
168
+ private Object removeReactiveAttribute (Model model , String name ) {
169
+ for ( Map . Entry < String , Object > entry : model .asMap ().entrySet ()) {
170
+ if (entry . getKey (). startsWith ( name )) {
171
+ ReactiveAdapter adapter = getAdapterRegistry (). getAdapter ( null , entry . getValue ());
172
+ if ( adapter != null ) {
173
+ if ( entry . getKey (). equals ( name + ClassUtils . getShortName ( adapter . getReactiveType ()))) {
174
+ // Remove since we will be re-inserting the resolved attribute value
175
+ model . asMap (). remove ( entry . getKey ());
176
+ return entry . getValue () ;
202
177
}
203
- String name = attributeName + ClassUtils .getShortName (adapter .getReactiveType ());
204
- return entry .getKey ().equals (name );
205
- })
206
- .findFirst ()
207
- .map (entry -> {
208
- // Remove since we will be re-inserting the resolved attribute value
209
- model .asMap ().remove (entry .getKey ());
210
- return entry .getValue ();
211
- })
212
- .orElse (null );
178
+ }
179
+ }
180
+ }
181
+ return null ;
213
182
}
214
183
215
184
private Mono <?> createAttribute (
@@ -274,6 +243,26 @@ public Mono<Map<String, Object>> getValuesToBind(WebExchangeDataBinder binder, S
274
243
return binder .getValuesToBind (exchange );
275
244
}
276
245
246
+ /**
247
+ * Determine if binding should be disabled for the supplied {@link MethodParameter},
248
+ * based on the {@link ModelAttribute#binding} annotation attribute.
249
+ * @since 5.2.15
250
+ */
251
+ private boolean bindingDisabled (MethodParameter parameter ) {
252
+ ModelAttribute modelAttribute = parameter .getParameterAnnotation (ModelAttribute .class );
253
+ return (modelAttribute != null && !modelAttribute .binding ());
254
+ }
255
+
256
+ /**
257
+ * Extension point to bind the request to the target object.
258
+ * @param binder the data binder instance to use for the binding
259
+ * @param exchange the current request
260
+ * @since 5.2.6
261
+ */
262
+ protected Mono <Void > bindRequestParameters (WebExchangeDataBinder binder , ServerWebExchange exchange ) {
263
+ return binder .bind (exchange );
264
+ }
265
+
277
266
private boolean hasErrorsArgument (MethodParameter parameter ) {
278
267
int i = parameter .getParameterIndex ();
279
268
Class <?>[] paramTypes = parameter .getExecutable ().getParameterTypes ();
0 commit comments