25
25
import java .util .List ;
26
26
import java .util .Locale ;
27
27
import java .util .Map ;
28
+ import java .util .TreeMap ;
28
29
29
30
import org .junit .Before ;
30
31
import org .junit .Test ;
45
46
import org .springframework .http .server .reactive .ServerHttpResponse ;
46
47
import org .springframework .mock .http .server .reactive .test .MockServerHttpRequest ;
47
48
import org .springframework .mock .http .server .reactive .test .MockServerHttpResponse ;
48
- import org .springframework .ui .ExtendedModelMap ;
49
+ import org .springframework .ui .ConcurrentModel ;
49
50
import org .springframework .ui .Model ;
50
51
import org .springframework .web .bind .annotation .ModelAttribute ;
51
52
import org .springframework .web .bind .annotation .ResponseStatus ;
52
53
import org .springframework .web .reactive .HandlerResult ;
53
54
import org .springframework .web .reactive .accept .HeaderContentTypeResolver ;
54
55
import org .springframework .web .reactive .accept .RequestedContentTypeResolver ;
55
56
import org .springframework .web .reactive .result .ResolvableMethod ;
57
+ import org .springframework .web .reactive .result .method .BindingContext ;
56
58
import org .springframework .web .server .NotAcceptableStatusException ;
57
59
import org .springframework .web .server .ServerWebExchange ;
58
60
import org .springframework .web .server .adapter .DefaultServerWebExchange ;
61
63
62
64
import static java .nio .charset .StandardCharsets .UTF_8 ;
63
65
import static org .junit .Assert .assertEquals ;
64
- import static org .junit .Assert .assertNotNull ;
65
66
import static org .mockito .Mockito .mock ;
66
67
import static org .springframework .core .ResolvableType .forClass ;
67
68
import static org .springframework .core .ResolvableType .forClassWithGenerics ;
@@ -80,7 +81,7 @@ public class ViewResolutionResultHandlerTests {
80
81
81
82
private ServerWebExchange exchange ;
82
83
83
- private Model model = new ExtendedModelMap ();
84
+ private final BindingContext bindingContext = new BindingContext ();
84
85
85
86
86
87
@ Before
@@ -114,7 +115,7 @@ private void testSupports(ResolvableType type, boolean result) {
114
115
private void testSupports (ResolvableMethod resolvableMethod , boolean result ) {
115
116
ViewResolutionResultHandler resultHandler = resultHandler (mock (ViewResolver .class ));
116
117
MethodParameter returnType = resolvableMethod .resolveReturnType ();
117
- HandlerResult handlerResult = new HandlerResult (new Object (), null , returnType , this .model );
118
+ HandlerResult handlerResult = new HandlerResult (new Object (), null , returnType , this .bindingContext );
118
119
assertEquals (result , resultHandler .supports (handlerResult ));
119
120
}
120
121
@@ -156,7 +157,7 @@ public void handleReturnValueTypes() throws Exception {
156
157
assertEquals (HttpStatus .PARTIAL_CONTENT , this .exchange .getResponse ().getStatusCode ());
157
158
158
159
returnType = forClass (Model .class );
159
- returnValue = new ExtendedModelMap ().addAttribute ("name" , "Joe" );
160
+ returnValue = new ConcurrentModel ().addAttribute ("name" , "Joe" );
160
161
testHandle ("/account" , returnType , returnValue , "account: {id=123, name=Joe}" , resolver );
161
162
162
163
returnType = forClass (Map .class );
@@ -190,8 +191,8 @@ public void defaultViewName() throws Exception {
190
191
}
191
192
192
193
private void testDefaultViewName (Object returnValue , ResolvableType type ) throws URISyntaxException {
193
- Model model = new ExtendedModelMap ().addAttribute ("id" , "123" );
194
- HandlerResult result = new HandlerResult (new Object (), returnValue , returnType (type ), model );
194
+ this . bindingContext . getModel ().addAttribute ("id" , "123" );
195
+ HandlerResult result = new HandlerResult (new Object (), returnValue , returnType (type ), this . bindingContext );
195
196
ViewResolutionResultHandler handler = resultHandler (new TestViewResolver ("account" ));
196
197
197
198
this .request .setUri ("/account" );
@@ -210,8 +211,8 @@ private void testDefaultViewName(Object returnValue, ResolvableType type) throws
210
211
@ Test
211
212
public void unresolvedViewName () throws Exception {
212
213
String returnValue = "account" ;
213
- ResolvableType type = forClass (String .class );
214
- HandlerResult result = new HandlerResult (new Object (), returnValue , returnType ( type ) , this .model );
214
+ MethodParameter returnType = returnType ( forClass (String .class ) );
215
+ HandlerResult result = new HandlerResult (new Object (), returnValue , returnType , this .bindingContext );
215
216
216
217
this .request .setUri ("/path" );
217
218
Mono <Void > mono = resultHandler ().handleResult (this .exchange , result );
@@ -225,8 +226,8 @@ public void unresolvedViewName() throws Exception {
225
226
@ Test
226
227
public void contentNegotiation () throws Exception {
227
228
TestBean value = new TestBean ("Joe" );
228
- ResolvableType type = forClass (TestBean .class );
229
- HandlerResult handlerResult = new HandlerResult (new Object (), value , returnType ( type ) , this .model );
229
+ MethodParameter returnType = returnType ( forClass (TestBean .class ) );
230
+ HandlerResult handlerResult = new HandlerResult (new Object (), value , returnType , this .bindingContext );
230
231
231
232
this .request .setHeader ("Accept" , "application/json" );
232
233
this .request .setUri ("/account" );
@@ -244,8 +245,8 @@ public void contentNegotiation() throws Exception {
244
245
@ Test
245
246
public void contentNegotiationWith406 () throws Exception {
246
247
TestBean value = new TestBean ("Joe" );
247
- ResolvableType type = forClass (TestBean .class );
248
- HandlerResult handlerResult = new HandlerResult (new Object (), value , returnType ( type ) , this .model );
248
+ MethodParameter returnType = returnType ( forClass (TestBean .class ) );
249
+ HandlerResult handlerResult = new HandlerResult (new Object (), value , returnType , this .bindingContext );
249
250
250
251
this .request .setHeader ("Accept" , "application/json" );
251
252
this .request .setUri ("/account" );
@@ -260,13 +261,13 @@ public void contentNegotiationWith406() throws Exception {
260
261
261
262
@ Test
262
263
public void modelWithAsyncAttributes () throws Exception {
263
- Model model = new ExtendedModelMap ();
264
- model .addAttribute ("bean1" , Mono .just (new TestBean ("Bean1" )));
265
- model .addAttribute ("bean2" , Single .just (new TestBean ("Bean2" )));
266
- model .addAttribute ("empty" , Mono .empty ());
264
+ this . bindingContext . getModel ()
265
+ .addAttribute ("bean1" , Mono .just (new TestBean ("Bean1" )))
266
+ .addAttribute ("bean2" , Single .just (new TestBean ("Bean2" )))
267
+ .addAttribute ("empty" , Mono .empty ());
267
268
268
269
ResolvableType type = forClass (void .class );
269
- HandlerResult result = new HandlerResult (new Object (), null , returnType (type ), model );
270
+ HandlerResult result = new HandlerResult (new Object (), null , returnType (type ), this . bindingContext );
270
271
ViewResolutionResultHandler handler = resultHandler (new TestViewResolver ("account" ));
271
272
272
273
this .request .setUri ("/account" );
@@ -304,9 +305,11 @@ private void testHandle(String path, ResolvableType returnType, Object returnVal
304
305
private void testHandle (String path , ResolvableMethod resolvableMethod , Object returnValue ,
305
306
String responseBody , ViewResolver ... resolvers ) throws URISyntaxException {
306
307
307
- Model model = new ExtendedModelMap ().addAttribute ("id" , "123" );
308
+ Model model = this .bindingContext .getModel ();
309
+ model .asMap ().clear ();
310
+ model .addAttribute ("id" , "123" );
308
311
MethodParameter returnType = resolvableMethod .resolveReturnType ();
309
- HandlerResult result = new HandlerResult (new Object (), returnValue , returnType , model );
312
+ HandlerResult result = new HandlerResult (new Object (), returnValue , returnType , this . bindingContext );
310
313
this .request .setUri (path );
311
314
resultHandler (resolvers ).handleResult (this .exchange , result ).block (Duration .ofSeconds (5 ));
312
315
assertResponseBody (responseBody );
@@ -375,12 +378,12 @@ public List<MediaType> getSupportedMediaTypes() {
375
378
376
379
@ Override
377
380
public Mono <Void > render (Map <String , ?> model , MediaType mediaType , ServerWebExchange exchange ) {
378
- String value = this .name + ": " + model .toString ();
379
- assertNotNull (value );
380
381
ServerHttpResponse response = exchange .getResponse ();
381
382
if (mediaType != null ) {
382
383
response .getHeaders ().setContentType (mediaType );
383
384
}
385
+ model = new TreeMap <>(model );
386
+ String value = this .name + ": " + model .toString ();
384
387
ByteBuffer byteBuffer = ByteBuffer .wrap (value .getBytes (UTF_8 ));
385
388
DataBuffer dataBuffer = new DefaultDataBufferFactory ().wrap (byteBuffer );
386
389
return response .writeWith (Flux .just (dataBuffer ));
0 commit comments