RSocket responders can be implemented as methods with @MessageMapping
and @ConnectMapping
annotations. Methods annotated with @MessageMapping
handle individual requests, while methods annotated
with @ConnectMapping
handle connection-level events (setting and pushing metadata). Annotated
responders are supported symmetrically for both server-side and client-side responses.
Server-side responders
To use annotated server-side responders, add RSocketMessageHandler
into the Spring
configuration to detect beans marked with the @Controller
annotation with methods annotated with @MessageMapping
and @ConnectMapping
:
@Configuration
static class ServerConfig {
@Bean
public RSocketMessageHandler rsocketMessageHandler() {
RSocketMessageHandler handler = new RSocketMessageHandler();
handler.routeMatcher(new PathPatternRouteMatcher());
return handler;
}
}
@Configuration
class ServerConfig {
@Bean
fun rsocketMessageHandler() = RSocketMessageHandler().apply {
routeMatcher = PathPatternRouteMatcher()
}
}
Then start the RSocket server via the RSocket API for Java and connect the RSocketMessageHandler
to the responder like this:
ApplicationContext context = ... ;
RSocketMessageHandler handler = context.getBean(RSocketMessageHandler.class);
CloseableChannel server =
RSocketServer.create(handler.responder())
.bind(TcpServerTransport.create("localhost", 7000))
.block();
import org.springframework.beans.factory.getBean
val context: ApplicationContext = ...
val handler = context.getBean<RSocketMessageHandler>()
val server = RSocketServer.create(handler.responder())
.bind(TcpServerTransport.create("localhost", 7000))
.awaitSingle()
RSocketMessageHandler
by default supports composite metadata and routing.
You can configure its MetadataExtractor if you need to switch to a different MIME type or register additional MIME
metadata types.
You will need to configure the Encoder
and Decoder
instances, that
are required to support metadata and data formats. To implement codecs, you will most likely need the spring-web
module.
By default, SimpleRouteMatcher
is used to negotiate routes through
AntPathMatcher
. We recommend connecting PathPatternRouteMatcher
from
spring-web
for efficient route matching. RSocket routes can be hierarchical, but are not URL paths.
Both route matchers are configured to use "." as the default delimiter, and there is no URL decoding as is the case
with HTTP URLs.
RSocketMessageHandler
can be configured via RSocketStrategies
,
which can be useful if you need to share configuration between client and server in the same process:
@Configuration
static class ServerConfig {
@Bean
public RSocketMessageHandler rsocketMessageHandler() {
RSocketMessageHandler handler = new RSocketMessageHandler();
handler.setRSocketStrategies(rsocketStrategies());
return handler;
}
@Bean
public RSocketStrategies rsocketStrategies() {
return RSocketStrategies.builder()
.encoders(encoders -> encoders.add(new Jackson2CborEncoder()))
.decoders(decoders -> decoders.add(new Jackson2CborDecoder()))
.routeMatcher(new PathPatternRouteMatcher())
.build();
}
}
@Configuration
class ServerConfig {
@Bean
fun rsocketMessageHandler() = RSocketMessageHandler().apply {
rSocketStrategies = rsocketStrategies()
}
@Bean
fun rsocketStrategies() = RSocketStrategies.builder()
.encoders { it.add(Jackson2CborEncoder()) }
.decoders { it.add(Jackson2CborDecoder()) }
.routeMatcher(PathPatternRouteMatcher())
.build()
}
Client-side responders
Annotated client-side responders must be configured in RSocketRequester.Builder
.
@MessageMapping
Once the responder configuration for the server or client has been configured,
methods with the @MessageMapping
annotation can be used as follows:
@Controller
public class RadarsController {
@MessageMapping("locate.radars.within")
public Flux<AirportLocation> radars(MapRequest request) {
// ...
}
}
@Controller
class RadarsController {
@MessageMapping("locate.radars.within")
fun radars(request: MapRequest): Flow<AirportLocation> {
// ...
}
}
The above method, marked with the @MessageMapping
annotation, responds to an interaction of type
Request-Stream with the route "locate.radars.within". It supports a flexible method signature with the ability to
use the following method arguments:
Method argument | Description |
---|---|
|
Request payload. This can be a concrete value of asynchronous types such as Note: The use of an annotation is optional. A method argument that is neither a prime type nor one of the other supported arguments is taken to be the expected payload. |
|
Requester for transmitting requests to the receiving side. |
|
The value extracted from the route based on variables in the mapping template, for example |
|
Metadata value registered to retrieve. |
|
All metadata values registered for retrieval. |
The return value is expected to be one or more objects that will be serialized as useful response data.
These can be asynchronous types such as Mono
or Flux
, a concrete value, or
void
or an asynchronous type without a value such as Mono<Void>
.
The type of
RSocket interaction that a method annotated with @MessageMapping
supports is determined by the
cardinality of the input set (i.e. the argument annotated with @Payload
) and output, where cardinality
means the following:
Power of the set | Description |
---|---|
1 |
Either an explicit value or an asynchronous single-value type such as |
Many |
A multivalued asynchronous type, such as |
0 |
In the case of input, this means that the method does not have an argument annotated with
In the case of output, this is |
The table below shows all input and output set power combinations and the corresponding interaction type(s):
Input set cardinality | Output set cardinality | Interaction types |
---|---|---|
0, 1 |
0 |
Fire-and-Forget, Request-Response |
0, 1 |
1 |
Request-Response |
0, 1 |
Set |
Request-Stream |
Set |
0, 1, set |
Request-Channel |
@ConnectMapping
The @ConnectMapping
annotation handles the SETUP
frame at
the beginning of an RSocket connection establishment and all subsequent notifications about pushing metadata through
frame METADATA_PUSH
, i.e. metadataPush(Payload)
in io.rsocket.RSocket
.
Methods with the @ConnectMapping
annotation support the same arguments as and methods with the
@MessageMapping annotation, but rely on metadata and data from the SETUP
and METADATA_PUSH
frames. The @ConnectMapping
annotation can be provided with a template to limit the processing
procedure to specific connections that have a route in the metadata, and if no templates are declared, then all
connections will match.
Methods annotated @ConnectMapping
cannot return data, so they must be
declared using void
or Mono<Void>
as the return value. If the processing procedure
returns an error for a new connection, then the connection is rejected. The processing procedure should not be
delayed so that requests to RSocketRequester
can be made for a specific connection.
GO TO FULL VERSION