GH-3207: RSocket inbound: decode each flux item (#3208)

* GH-3207: RSocket inbound: decode each flux item

Fixes https://github.com/spring-projects/spring-integration/issues/3207

Previously an incoming RSocket Publisher has been decoded as a single unit
leading to extra work on the client side, e.g. a delimiter has to be provided
to treat each payload item as independent

* To have a consistency with Spring Messaging and its `PayloadMethodArgumentResolver`
change an `RSocketInboundGateway` to process inbound payloads as `Flux` and decode
each item independently.
* Change `RSocketDslTests` to remove delimiters and make it consistent with the regular
`RSocketRequester` client

* * Add `decodeFluxAsUnit` option into `RSocketInboundGateway`
* Document the change
This commit is contained in:
Artem Bilan
2020-03-10 16:07:01 -04:00
committed by GitHub
parent 1511dd8748
commit c45cc66a84
9 changed files with 103 additions and 13 deletions

View File

@@ -25,6 +25,7 @@
auto-startup="false"
request-channel="requestChannel"
rsocket-strategies="rsocketStrategies"
request-element-type="byte[]"/>
request-element-type="byte[]"
decode-flux-as-unit="true"/>
</beans>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2019 the original author or authors.
* Copyright 2019-2020 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.
@@ -44,7 +44,7 @@ class RSocketInboundGatewayParserTests {
private RSocketInboundGateway inboundGateway;
@Test
void testOutboundGatewayParser() {
void testInboundGatewayParser() {
assertThat(TestUtils.getPropertyValue(this.inboundGateway, "rsocketConnector"))
.isSameAs(this.clientRSocketConnector);
assertThat(TestUtils.getPropertyValue(this.inboundGateway, "rsocketStrategies"))
@@ -54,6 +54,7 @@ class RSocketInboundGatewayParserTests {
.isEqualTo(byte[].class);
assertThat(this.inboundGateway.getInteractionModels())
.containsExactly(RSocketInteractionModel.fireAndForget, RSocketInteractionModel.requestChannel);
assertThat(TestUtils.getPropertyValue(this.inboundGateway, "decodeFluxAsUnit", Boolean.class)).isTrue();
}
}

View File

@@ -31,6 +31,8 @@ import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.rsocket.ClientRSocketConnector;
import org.springframework.integration.rsocket.RSocketInteractionModel;
import org.springframework.integration.rsocket.ServerRSocketConnector;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
@@ -48,17 +50,30 @@ public class RSocketDslTests {
@Autowired
@Qualifier("rsocketUpperCaseRequestFlow.gateway")
private Function<Flux<String>, Flux<String>> rsocketUpperCaseFlowFunction;
private Function<Object, Flux<String>> rsocketUpperCaseFlowFunction;
@Test
void testRsocketUpperCaseFlows() {
Flux<String> result = this.rsocketUpperCaseFlowFunction.apply(Flux.just("a\n", "b\n", "c\n"));
Flux<String> result = this.rsocketUpperCaseFlowFunction.apply(Flux.just("a", "b", "c"));
StepVerifier.create(result)
.expectNext("A", "B", "C")
.verifyComplete();
}
@Test
void testRsocketUpperCaseWholeFlows() {
Message<Flux<String>> testMessage =
MessageBuilder.withPayload(Flux.just("a", "b", "c", "\n"))
.setHeader("route", "/uppercaseWhole")
.build();
Flux<String> result = this.rsocketUpperCaseFlowFunction.apply(testMessage);
StepVerifier.create(result)
.expectNext("ABC")
.verifyComplete();
}
@Configuration
@EnableIntegration
public static class TestConfiguration {
@@ -80,7 +95,8 @@ public class RSocketDslTests {
public IntegrationFlow rsocketUpperCaseRequestFlow(ClientRSocketConnector clientRSocketConnector) {
return IntegrationFlows
.from(Function.class)
.handle(RSockets.outboundGateway("/uppercase")
.handle(RSockets.outboundGateway(message ->
message.getHeaders().getOrDefault("route", "/uppercase"))
.interactionModel((message) -> RSocketInteractionModel.requestChannel)
.expectedResponseType("T(java.lang.String)")
.clientRSocketConnector(clientRSocketConnector),
@@ -100,6 +116,16 @@ public class RSocketDslTests {
.get();
}
@Bean
public IntegrationFlow rsocketUpperCaseWholeFlow() {
return IntegrationFlows
.from(RSockets.inboundGateway("/uppercaseWhole")
.interactionModels(RSocketInteractionModel.requestChannel)
.decodeFluxAsUnit(true))
.<Flux<String>, Flux<String>>transform((flux) -> flux.map(String::toUpperCase))
.get();
}
}
}