From 5b6c1272831445c65873010a77c383e84b56b464 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Fri, 28 Jul 2023 12:46:58 +0300 Subject: [PATCH] Polishing Closes gh-30936 --- .../modules/ROOT/pages/rsocket.adoc | 82 +++++++++++-------- .../support/RSocketMessageHandler.java | 8 +- .../rsocket/service/RSocketExchange.java | 8 +- .../service/RSocketServiceProxyFactory.java | 2 +- 4 files changed, 58 insertions(+), 42 deletions(-) diff --git a/framework-docs/modules/ROOT/pages/rsocket.adoc b/framework-docs/modules/ROOT/pages/rsocket.adoc index 02721503de..ade8b42c06 100644 --- a/framework-docs/modules/ROOT/pages/rsocket.adoc +++ b/framework-docs/modules/ROOT/pages/rsocket.adoc @@ -137,12 +137,12 @@ demonstrate its API and protocol features. The `spring-messaging` module contains the following: -* xref:rsocket.adoc#rsocket-requester[RSocketRequester] -- fluent API to make requests through an `io.rsocket.RSocket` - with data and metadata encoding/decoding. -* xref:rsocket.adoc#rsocket-interface[RSocket Interfaces] -- `@RSocketExchange` annotated -interfaces for making requests. +* xref:rsocket.adoc#rsocket-requester[RSocketRequester] -- fluent API to make requests +through an `io.rsocket.RSocket` with data and metadata encoding/decoding. * xref:rsocket.adoc#rsocket-annot-responders[Annotated Responders] -- `@MessageMapping` and `@RSocketExchange` annotated handler methods for responding. +* xref:rsocket.adoc#rsocket-interface[RSocket Interface] -- RSocket service declaration +as Java interface with `@RSocketExchange` methods, for use as requester or responder. The `spring-web` module contains `Encoder` and `Decoder` implementations such as Jackson CBOR/JSON, and Protobuf that RSocket applications will likely need. It also contains the @@ -864,15 +864,16 @@ interaction type(s): |=== + [[rsocket-annot-rsocketexchange]] === @RSocketExchange -While `@MessageMapping` is only supported for responding, `@RSocketExchange` -can be used both to create an annotated responder -and xref:rsocket.adoc#rsocket-interface[an RSocket Interface] that allows -making requests. +As an alternative to `@MessageMapping`, you can also handle requests with +`@RSocketExchange` methods. Such methods are declared on an +xref:rsocket-interface[RSocket Interface] and can be used as a requester via +`RSocketServiceProxyFactory` or as a responder. -`@RSocketExchange` can be used as follows to create responder methods: +For example, to handle requests as a responder: [tabs] ====== @@ -880,10 +881,15 @@ Java:: + [source,java,indent=0,subs="verbatim,quotes",role="primary"] ---- - @Controller - public class RadarsController { + public interface RadarsService { @RSocketExchange("locate.radars.within") + Flux radars(MapRequest request); + } + + @Controller + public class RadarsController implements RadarsService { + public Flux radars(MapRequest request) { // ... } @@ -894,28 +900,32 @@ Kotlin:: + [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] ---- -@Controller -class RadarsController { + interface RadarsService { - @RSocketExchange("locate.radars.within") - fun radars(request: MapRequest): Flow { - // ... + @RSocketExchange("locate.radars.within") + fun radars(request: MapRequest): Flow + } + + @Controller + class RadarsController : RadarsService { + + override fun radars(request: MapRequest): Flow { + // ... + } } -} ---- ====== -`@RSocketExhange` supports a very similar method signature to `@MessageMapping`, -however, since it needs to be suitable both for requester and responder use, -there are slight differences. Notably, while `@MessageMapping` accepts -a `String` array as its `value` parameter, only a single `String` can be passed -as the `value` of `@RSocketExchange`. +There some differences between `@RSocketExhange` and `@MessageMapping` since the +former needs to remain suitable for requester and responder use. For example, while +`@MessageMapping` can be declared to handle any number of routes and each route can +be a pattern, `@RSocketExchange` must be declared with a single, concrete route. There are +also small differences in the supported method parameters related to metadata, see +xref:rsocket-annot-messagemapping[@MessageMapping] and +xref:rsocket-interface[RSocket Interface] for a list of supported parameters. -When it comes to possible return values and the way we establish supported -RSocket interaction types, it works in the same way as with `@MessageMapping`. - -Similarly to `@MessageMapping`, `@RSocketExchange` can also be used at class -level to specify a common prefix for all the method routes within the class. +`@RSocketExchange` can be used at the type level to specify a common prefix for all routes +for a given RSocket service interface. [[rsocket-annot-connectmapping]] @@ -1052,12 +1062,13 @@ Kotlin:: [[rsocket-interface]] == RSocket Interface -The Spring Framework lets you define an RSocket service as a Java interface with annotated -methods for RSocket exchanges. You can then generate a proxy that implements this interface -and performs the exchanges. This helps to simplify RSocket remote access by wrapping the -use of the underlying xref:rsocket.adoc#rsocket-requester[RSocketRequester]. +The Spring Framework lets you define an RSocket service as a Java interface with +`@RSocketExchange` methods. You can pass such an interface to `RSocketServiceProxyFactory` +to create a proxy which performs requests through an +xref:rsocket.adoc#rsocket-requester[RSocketRequester]. You can also implement the +interface as a responder that handles requests. -One, declare an interface with `@RSocketExchange` methods: +Start by creating the interface with `@RSocketExchange` methods: [source,java,indent=0,subs="verbatim,quotes"] ---- @@ -1071,7 +1082,7 @@ One, declare an interface with `@RSocketExchange` methods: } ---- -Two, create a proxy that will perform the declared RSocket exchanges: +Now you can create a proxy that performs requests when methods are called: [source,java,indent=0,subs="verbatim,quotes"] ---- @@ -1081,8 +1092,9 @@ Two, create a proxy that will perform the declared RSocket exchanges: RepositoryService service = factory.createClient(RadarService.class); ---- -NOTE: Apart from RSocket interface services, `@RSocketExchange` can also -be used to create xref:rsocket.adoc#rsocket-annot-rsocketexchange[annotated responders]. +You can also implement the interface to handle requests as a responder. +See xref:rsocket.adoc#rsocket-annot-rsocketexchange[Annotated Responders]. + [[rsocket-interface-method-parameters]] diff --git a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/RSocketMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/RSocketMessageHandler.java index 2df213e3b4..a13942d77e 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/RSocketMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/RSocketMessageHandler.java @@ -60,10 +60,10 @@ import org.springframework.util.RouteMatcher; import org.springframework.util.StringUtils; /** - * Extension of {@link MessageMappingMessageHandler} for handling RSocket - * requests with {@link ConnectMapping @ConnectMapping}, - * {@link MessageMapping @MessageMapping} - * and {@link RSocketExchange @RSocketExchange} methods. + * Extension of {@link MessageMappingMessageHandler} to handle RSocket + * requests with {@link MessageMapping @MessageMapping} and + * {@link ConnectMapping @ConnectMapping} methods, also supporting use of + * {@link RSocketExchange @RSocketExchange}. * *

For server scenarios this class can be declared as a bean in Spring * configuration and that would detect {@code @MessageMapping} methods in diff --git a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketExchange.java b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketExchange.java index 5a6125038e..2fc9b0cd9f 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketExchange.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketExchange.java @@ -25,8 +25,12 @@ import java.lang.annotation.Target; import org.springframework.aot.hint.annotation.Reflective; /** - * Annotation to declare a method on an RSocket service interface as an RSocket - * endpoint. The endpoint route is determined through the annotation attribute, + * Annotation to declare an RSocket endpoint on an RSocket service interface. + * Supported for use as an RSocket requester via + * {@link RSocketServiceProxyFactory}, and as a responder by implementing the + * interface to handle requests. + * + *

The endpoint route is determined through the annotation attribute, * and through the method arguments. * *

The annotation is supported at the type level to express a common route, diff --git a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketServiceProxyFactory.java b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketServiceProxyFactory.java index 65a3d3a56a..ffa2833edf 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketServiceProxyFactory.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/service/RSocketServiceProxyFactory.java @@ -39,7 +39,7 @@ import org.springframework.util.Assert; import org.springframework.util.StringValueResolver; /** - * Factory for creating a client proxy given an RSocket service interface with + * Factory to create a client proxy from an RSocket service interface with * {@link RSocketExchange @RSocketExchange} methods. * *

To create an instance, use static methods to obtain a