1616
1717package org .springframework .web .reactive .result .method .annotation ;
1818
19- import java .lang . reflect . Method ;
19+ import java .time . Duration ;
2020import java .util .Optional ;
2121
22+ import io .reactivex .Single ;
2223import org .junit .Before ;
2324import org .junit .Test ;
2425import reactor .core .publisher .Mono ;
2526import reactor .test .StepVerifier ;
2627
2728import org .springframework .context .annotation .AnnotationConfigApplicationContext ;
28- import org .springframework .core .DefaultParameterNameDiscoverer ;
29- import org .springframework .core .GenericTypeResolver ;
3029import org .springframework .core .MethodParameter ;
3130import org .springframework .core .ReactiveAdapterRegistry ;
32- import org .springframework .core .annotation .SynthesizingMethodParameter ;
3331import org .springframework .format .support .DefaultFormattingConversionService ;
3432import org .springframework .mock .http .server .reactive .test .MockServerHttpRequest ;
3533import org .springframework .mock .web .test .server .MockServerWebExchange ;
36- import org .springframework .util .ReflectionUtils ;
3734import org .springframework .web .bind .annotation .RequestAttribute ;
3835import org .springframework .web .bind .support .ConfigurableWebBindingInitializer ;
36+ import org .springframework .web .method .ResolvableMethod ;
3937import org .springframework .web .reactive .BindingContext ;
4038import org .springframework .web .server .ServerWebInputException ;
4139
4543import static org .junit .Assert .assertNull ;
4644import static org .junit .Assert .assertSame ;
4745import static org .junit .Assert .assertTrue ;
48- import static org .junit . Assert . fail ;
46+ import static org .springframework . web . method . MvcAnnotationPredicates . requestAttribute ;
4947
5048/**
5149 * Unit tests for {@link RequestAttributeMethodArgumentResolver}.
@@ -58,37 +56,36 @@ public class RequestAttributeMethodArgumentResolverTests {
5856
5957 private final MockServerWebExchange exchange = MockServerWebExchange .from (MockServerHttpRequest .get ("/" ));
6058
61- private Method handleMethod ;
59+ private final ResolvableMethod testMethod = ResolvableMethod .on (getClass ())
60+ .named ("handleWithRequestAttribute" ).build ();
6261
6362
6463 @ Before
6564 public void setup () throws Exception {
6665 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext ();
6766 context .refresh ();
68- ReactiveAdapterRegistry adapterRegistry = new ReactiveAdapterRegistry ();
69- this .resolver = new RequestAttributeMethodArgumentResolver (context .getBeanFactory (), adapterRegistry );
70- this .handleMethod = ReflectionUtils .findMethod (getClass (), "handleWithRequestAttribute" , (Class <?>[]) null );
67+ ReactiveAdapterRegistry registry = new ReactiveAdapterRegistry ();
68+ this .resolver = new RequestAttributeMethodArgumentResolver (context .getBeanFactory (), registry );
7169 }
7270
7371
7472 @ Test
7573 public void supportsParameter () throws Exception {
76- assertTrue (this .resolver .supportsParameter (new MethodParameter (this .handleMethod , 0 )));
77- assertFalse (this .resolver .supportsParameter (new MethodParameter (this .handleMethod , 4 )));
78- try {
79- this .resolver .supportsParameter (new MethodParameter (this .handleMethod , 5 ));
80- fail ();
81- }
82- catch (IllegalStateException ex ) {
83- assertTrue ("Unexpected error message:\n " + ex .getMessage (),
84- ex .getMessage ().startsWith (
85- "RequestAttributeMethodArgumentResolver doesn't support reactive type wrapper" ));
86- }
74+
75+ assertTrue (this .resolver .supportsParameter (
76+ this .testMethod .annot (requestAttribute ().noName ()).arg (Foo .class )));
77+
78+ // SPR-16158
79+ assertTrue (this .resolver .supportsParameter (
80+ this .testMethod .annotPresent (RequestAttribute .class ).arg (Mono .class , Foo .class )));
81+
82+ assertFalse (this .resolver .supportsParameter (
83+ this .testMethod .annotNotPresent (RequestAttribute .class ).arg ()));
8784 }
8885
8986 @ Test
9087 public void resolve () throws Exception {
91- MethodParameter param = initMethodParameter ( 0 );
88+ MethodParameter param = this . testMethod . annot ( requestAttribute (). noName ()). arg ( Foo . class );
9289 Mono <Object > mono = this .resolver .resolveArgument (param , new BindingContext (), this .exchange );
9390 StepVerifier .create (mono )
9491 .expectNextCount (0 )
@@ -103,7 +100,7 @@ public void resolve() throws Exception {
103100
104101 @ Test
105102 public void resolveWithName () throws Exception {
106- MethodParameter param = initMethodParameter ( 1 );
103+ MethodParameter param = this . testMethod . annot ( requestAttribute (). name ( "specialFoo" )). arg ( );
107104 Foo foo = new Foo ();
108105 this .exchange .getAttributes ().put ("specialFoo" , foo );
109106 Mono <Object > mono = this .resolver .resolveArgument (param , new BindingContext (), this .exchange );
@@ -112,7 +109,7 @@ public void resolveWithName() throws Exception {
112109
113110 @ Test
114111 public void resolveNotRequired () throws Exception {
115- MethodParameter param = initMethodParameter ( 2 );
112+ MethodParameter param = this . testMethod . annot ( requestAttribute (). name ( "foo" ). notRequired ()). arg ( );
116113 Mono <Object > mono = this .resolver .resolveArgument (param , new BindingContext (), this .exchange );
117114 assertNull (mono .block ());
118115
@@ -124,7 +121,7 @@ public void resolveNotRequired() throws Exception {
124121
125122 @ Test
126123 public void resolveOptional () throws Exception {
127- MethodParameter param = initMethodParameter ( 3 );
124+ MethodParameter param = this . testMethod . annot ( requestAttribute (). name ( "foo" )). arg ( Optional . class , Foo . class );
128125 Mono <Object > mono = this .resolver .resolveArgument (param , new BindingContext (), this .exchange );
129126
130127 assertNotNull (mono .block ());
@@ -146,12 +143,30 @@ public void resolveOptional() throws Exception {
146143 assertSame (foo , optional .get ());
147144 }
148145
146+ @ Test // SPR-16158
147+ public void resolveMonoParameter () throws Exception {
148+ MethodParameter param = this .testMethod .annot (requestAttribute ().noName ()).arg (Mono .class , Foo .class );
149149
150- private MethodParameter initMethodParameter (int parameterIndex ) {
151- MethodParameter param = new SynthesizingMethodParameter (this .handleMethod , parameterIndex );
152- param .initParameterNameDiscovery (new DefaultParameterNameDiscoverer ());
153- GenericTypeResolver .resolveParameterType (param , this .resolver .getClass ());
154- return param ;
150+ // Mono attribute
151+ Foo foo = new Foo ();
152+ Mono <Foo > fooMono = Mono .just (foo );
153+ this .exchange .getAttributes ().put ("fooMono" , fooMono );
154+ Mono <Object > mono = this .resolver .resolveArgument (param , new BindingContext (), this .exchange );
155+ assertSame (fooMono , mono .block (Duration .ZERO ));
156+
157+ // RxJava Single attribute
158+ Single <Foo > singleMono = Single .just (foo );
159+ this .exchange .getAttributes ().clear ();
160+ this .exchange .getAttributes ().put ("fooMono" , singleMono );
161+ mono = this .resolver .resolveArgument (param , new BindingContext (), this .exchange );
162+ Object value = mono .block (Duration .ZERO );
163+ assertTrue (value instanceof Mono );
164+ assertSame (foo , ((Mono <?>) value ).block (Duration .ZERO ));
165+
166+ // No attribute --> Mono.empty
167+ this .exchange .getAttributes ().clear ();
168+ mono = this .resolver .resolveArgument (param , new BindingContext (), this .exchange );
169+ assertSame (Mono .empty (), mono .block (Duration .ZERO ));
155170 }
156171
157172
@@ -161,8 +176,8 @@ private void handleWithRequestAttribute(
161176 @ RequestAttribute ("specialFoo" ) Foo namedFoo ,
162177 @ RequestAttribute (name ="foo" , required = false ) Foo notRequiredFoo ,
163178 @ RequestAttribute (name ="foo" ) Optional <Foo > optionalFoo ,
164- String notSupported ,
165- @ RequestAttribute Mono < Foo > alsoNotSupported ) {
179+ @ RequestAttribute Mono < Foo > fooMono ,
180+ String notSupported ) {
166181 }
167182
168183
0 commit comments