diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/PrincipalArgumentResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/PrincipalArgumentResolver.java index d469f940d7..df94490a5e 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/PrincipalArgumentResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/PrincipalArgumentResolver.java @@ -21,8 +21,8 @@ import java.security.Principal; import reactor.core.publisher.Mono; import org.springframework.core.MethodParameter; +import org.springframework.core.ReactiveAdapter; import org.springframework.core.ReactiveAdapterRegistry; -import org.springframework.util.Assert; import org.springframework.web.reactive.BindingContext; import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverSupport; import org.springframework.web.server.ServerWebExchange; @@ -36,6 +36,7 @@ import org.springframework.web.server.ServerWebExchange; */ public class PrincipalArgumentResolver extends HandlerMethodArgumentResolverSupport { + public PrincipalArgumentResolver(ReactiveAdapterRegistry adapterRegistry) { super(adapterRegistry); } @@ -43,15 +44,16 @@ public class PrincipalArgumentResolver extends HandlerMethodArgumentResolverSupp @Override public boolean supportsParameter(MethodParameter parameter) { - return checkParameterTypeNoReactiveWrapper(parameter, Principal.class::isAssignableFrom); + return checkParameterType(parameter, Principal.class::isAssignableFrom); } @Override public Mono resolveArgument(MethodParameter parameter, BindingContext context, ServerWebExchange exchange) { - Assert.isAssignable(Principal.class, parameter.getParameterType()); - return exchange.getPrincipal().cast(Object.class); + Mono principal = exchange.getPrincipal(); + ReactiveAdapter adapter = getAdapterRegistry().getAdapter(parameter.getParameterType()); + return adapter != null ? Mono.just(adapter.fromPublisher(principal)) : Mono.from(principal); } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/WebSessionArgumentResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/WebSessionArgumentResolver.java index d5895973e8..af1d3303a9 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/WebSessionArgumentResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/WebSessionArgumentResolver.java @@ -19,10 +19,9 @@ package org.springframework.web.reactive.result.method.annotation; import reactor.core.publisher.Mono; import org.springframework.core.MethodParameter; +import org.springframework.core.ReactiveAdapter; import org.springframework.core.ReactiveAdapterRegistry; -import org.springframework.util.Assert; import org.springframework.web.reactive.BindingContext; -import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver; import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverSupport; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebSession; @@ -36,6 +35,7 @@ import org.springframework.web.server.WebSession; */ public class WebSessionArgumentResolver extends HandlerMethodArgumentResolverSupport { + public WebSessionArgumentResolver(ReactiveAdapterRegistry adapterRegistry) { super(adapterRegistry); } @@ -43,15 +43,16 @@ public class WebSessionArgumentResolver extends HandlerMethodArgumentResolverSup @Override public boolean supportsParameter(MethodParameter parameter) { - return checkParameterTypeNoReactiveWrapper(parameter, WebSession.class::isAssignableFrom); + return checkParameterType(parameter, WebSession.class::isAssignableFrom); } @Override public Mono resolveArgument( MethodParameter parameter, BindingContext context, ServerWebExchange exchange) { - Assert.isAssignable(WebSession.class, parameter.getParameterType()); - return exchange.getSession().cast(Object.class); + Mono session = exchange.getSession(); + ReactiveAdapter adapter = getAdapterRegistry().getAdapter(parameter.getParameterType()); + return adapter != null ? Mono.just(adapter.fromPublisher(session)) : Mono.from(session); } } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/PrincipalArgumentResolverTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/PrincipalArgumentResolverTests.java new file mode 100644 index 0000000000..7da767a79a --- /dev/null +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/PrincipalArgumentResolverTests.java @@ -0,0 +1,85 @@ +/* + * Copyright 2002-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.web.reactive.result.method.annotation; + +import java.security.Principal; + +import io.reactivex.Single; +import org.junit.Test; +import reactor.core.publisher.Mono; + +import org.springframework.core.MethodParameter; +import org.springframework.core.ReactiveAdapterRegistry; +import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; +import org.springframework.web.method.ResolvableMethod; +import org.springframework.web.reactive.BindingContext; +import org.springframework.web.server.ServerWebExchange; + +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * Unit tests for {@link PrincipalArgumentResolver}. + * @author Rossen Stoyanchev + */ +public class PrincipalArgumentResolverTests { + + private final PrincipalArgumentResolver resolver = + new PrincipalArgumentResolver(new ReactiveAdapterRegistry()); + + private ResolvableMethod testMethod = ResolvableMethod.on(getClass()).named("handle").build(); + + + @Test + public void supportsParameter() throws Exception { + assertTrue(this.resolver.supportsParameter(this.testMethod.arg(Principal.class))); + assertTrue(this.resolver.supportsParameter(this.testMethod.arg(Mono.class, Principal.class))); + assertTrue(this.resolver.supportsParameter(this.testMethod.arg(Single.class, Principal.class))); + } + + + @Test + public void resolverArgument() throws Exception { + + BindingContext context = new BindingContext(); + Principal user = () -> "Joe"; + ServerWebExchange exchange = MockServerHttpRequest.get("/").build().toExchange() + .mutate().principal(Mono.just(user)).build(); + + MethodParameter param = this.testMethod.arg(Principal.class); + Object actual = this.resolver.resolveArgument(param, context, exchange).block(); + assertSame(user, actual); + + param = this.testMethod.arg(Mono.class, Principal.class); + actual = this.resolver.resolveArgument(param, context, exchange).block(); + assertTrue(Mono.class.isAssignableFrom(actual.getClass())); + assertSame(user, ((Mono) actual).block()); + + param = this.testMethod.arg(Single.class, Principal.class); + actual = this.resolver.resolveArgument(param, context, exchange).block(); + assertTrue(Single.class.isAssignableFrom(actual.getClass())); + assertSame(user, ((Single) actual).blockingGet()); + } + + + @SuppressWarnings("unused") + void handle( + Principal user, + Mono userMono, + Single singleUser) { + } + +} diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/WebSessionArgumentResolverTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/WebSessionArgumentResolverTests.java new file mode 100644 index 0000000000..d494f6bf64 --- /dev/null +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/WebSessionArgumentResolverTests.java @@ -0,0 +1,93 @@ +/* + * Copyright 2002-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.web.reactive.result.method.annotation; + +import java.time.Clock; + +import io.reactivex.Single; +import org.junit.Test; +import reactor.core.publisher.Mono; + +import org.springframework.core.MethodParameter; +import org.springframework.core.ReactiveAdapterRegistry; +import org.springframework.http.codec.ServerCodecConfigurer; +import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; +import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse; +import org.springframework.web.method.ResolvableMethod; +import org.springframework.web.reactive.BindingContext; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebSession; +import org.springframework.web.server.adapter.DefaultServerWebExchange; +import org.springframework.web.server.session.DefaultWebSession; +import org.springframework.web.server.session.WebSessionManager; + +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * Unit tests for {@link WebSessionArgumentResolver}. + * @author Rossen Stoyanchev + */ +public class WebSessionArgumentResolverTests { + + private final WebSessionArgumentResolver resolver = + new WebSessionArgumentResolver(new ReactiveAdapterRegistry()); + + private ResolvableMethod testMethod = ResolvableMethod.on(getClass()).named("handle").build(); + + + @Test + public void supportsParameter() throws Exception { + assertTrue(this.resolver.supportsParameter(this.testMethod.arg(WebSession.class))); + assertTrue(this.resolver.supportsParameter(this.testMethod.arg(Mono.class, WebSession.class))); + assertTrue(this.resolver.supportsParameter(this.testMethod.arg(Single.class, WebSession.class))); + } + + + @Test + public void resolverArgument() throws Exception { + + BindingContext context = new BindingContext(); + WebSession session = new DefaultWebSession("id", Clock.systemDefaultZone()); + WebSessionManager manager = exchange -> Mono.just(session); + MockServerHttpRequest request = MockServerHttpRequest.get("/").build(); + ServerWebExchange exchange = new DefaultServerWebExchange(request, new MockServerHttpResponse(), + manager, ServerCodecConfigurer.create()); + + MethodParameter param = this.testMethod.arg(WebSession.class); + Object actual = this.resolver.resolveArgument(param, context, exchange).block(); + assertSame(session, actual); + + param = this.testMethod.arg(Mono.class, WebSession.class); + actual = this.resolver.resolveArgument(param, context, exchange).block(); + assertTrue(Mono.class.isAssignableFrom(actual.getClass())); + assertSame(session, ((Mono) actual).block()); + + param = this.testMethod.arg(Single.class, WebSession.class); + actual = this.resolver.resolveArgument(param, context, exchange).block(); + assertTrue(Single.class.isAssignableFrom(actual.getClass())); + assertSame(session, ((Single) actual).blockingGet()); + } + + + @SuppressWarnings("unused") + void handle( + WebSession user, + Mono userMono, + Single singleUser) { + } + +}