Description
Currently, our RSocket support is mapping REQUEST_FNF
, REQUEST_RESPONSE
, REQUEST_STREAM
and REQUEST_CHANNEL
on @MessageMapping
annotated handler methods on one side, SETUP
and METADATA_PUSH
on @ConnectMapping
on the other.
Context of the issue
The case of "fire and forget" requests, where the requester sends a request and does not expect any response, can be interesting here in the context of our flexible signature support and the current mapping process.
While looking at our RSocket support with @snicoll, we considered a Controller handler that returns a response stream:
@MessageMapping("test")
public Flux<Long> test() {
return Flux.interval(Duration.ofSeconds(1));
}
If a requester calls this handler with a fire and forget interaction type:
Mono<Void> done = requesterBuilder.dataMimeType(MediaType.APPLICATION_CBOR)
.connectTcp("localhost", this.localPort)
.flatMap(req -> req.route("test").send());
Then we're getting the following exception on the server side:
java.lang.IllegalArgumentException: Missing 'rsocketResponse'
at org.springframework.util.Assert.notNull(Assert.java:198)
at org.springframework.messaging.rsocket.annotation.support.RSocketPayloadReturnValueHandler.handleEncodedContent(RSocketPayloadReturnValueHandler.java:65)
at org.springframework.messaging.handler.invocation.reactive.AbstractEncoderMethodReturnValueHandler.lambda$handleReturnValue$0(AbstractEncoderMethodReturnValueHandler.java:124)
at org.springframework.messaging.handler.invocation.reactive.ChannelSendOperator$WriteBarrier.onNext(ChannelSendOperator.java:194)
In this particular case (and in general), we can find pairs of handler definitions / rsocket interactions that mismatch in our mapping infrastructure. For example, a request can be mapped to a handler, the handler is executed but the returned subscriber is not subscribed to.
After chatting with @rstoyanchev, we thought that we should enforce a few design choices in our implementation.
Refining message mappings with handler return types
First, when mapping requests on handlers, returning more elements than expected should not be allowed, but returning less than expected should be permitted.
For example:
- a
REQUEST_FNF
should only be mapped on handlers that returnMono<Void>
orvoid
. Other types (evenMono<?>
) should not be considered for mapping. - a
REQUEST_RESPONSE
should only be mapped onMono
types, asFlux
might return more than expected. In this case, we could automaticallytake(1)
on the returned publisher, but this goes against the general behavior we've established in reactor and webflux so far.
Not allowing ambiguous mappings
Even in the light of this (restricting message mapping depending on the handler return type), we should not allow multiple handlers with the same route. If this happens, this will be treated as an error since the mapping is ambiguous.