Skip to content

Commit eacc531

Browse files
committed
Add dataMimeType to RSocketRequestBuilder
Closes gh-23012
1 parent 64f3dbb commit eacc531

File tree

4 files changed

+75
-24
lines changed

4 files changed

+75
-24
lines changed

spring-messaging/spring-messaging.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ dependencyManagement {
77
}
88
}
99

10-
def rsocketVersion = "0.12.2-RC3-SNAPSHOT"
10+
def rsocketVersion = "0.12.2-RC4-SNAPSHOT"
1111

1212
dependencies {
1313
compile(project(":spring-beans"))

spring-messaging/src/main/java/org/springframework/messaging/rsocket/DefaultRSocketRequesterBuilder.java

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.ArrayList;
2121
import java.util.List;
2222
import java.util.function.Consumer;
23+
import java.util.stream.Stream;
2324

2425
import io.rsocket.RSocketFactory;
2526
import io.rsocket.transport.ClientTransport;
@@ -28,6 +29,7 @@
2829
import reactor.core.publisher.Mono;
2930

3031
import org.springframework.lang.Nullable;
32+
import org.springframework.util.Assert;
3133
import org.springframework.util.MimeType;
3234

3335
/**
@@ -39,6 +41,9 @@
3941
*/
4042
final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder {
4143

44+
@Nullable
45+
private MimeType dataMimeType;
46+
4247
private List<Consumer<RSocketFactory.ClientRSocketFactory>> factoryConfigurers = new ArrayList<>();
4348

4449
@Nullable
@@ -47,6 +52,12 @@ final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder {
4752
private List<Consumer<RSocketStrategies.Builder>> strategiesConfigurers = new ArrayList<>();
4853

4954

55+
@Override
56+
public RSocketRequester.Builder dataMimeType(MimeType mimeType) {
57+
this.dataMimeType = mimeType;
58+
return this;
59+
}
60+
5061
@Override
5162
public RSocketRequester.Builder rsocketFactory(Consumer<RSocketFactory.ClientRSocketFactory> configurer) {
5263
this.factoryConfigurers.add(configurer);
@@ -81,17 +92,15 @@ public Mono<RSocketRequester> connect(ClientTransport transport) {
8192
}
8293

8394
private Mono<RSocketRequester> doConnect(ClientTransport transport) {
84-
RSocketStrategies rsocketStrategies = getRSocketStrategies();
85-
RSocketFactory.ClientRSocketFactory rsocketFactory = RSocketFactory.connect();
8695

87-
// 1. Apply default settings
88-
MimeType dataMimeType = getDefaultDataMimeType(rsocketStrategies);
89-
if (dataMimeType != null) {
90-
rsocketFactory.dataMimeType(dataMimeType.toString());
91-
}
96+
RSocketStrategies rsocketStrategies = getRSocketStrategies();
97+
Assert.isTrue(!rsocketStrategies.encoders().isEmpty(), "No encoders");
98+
Assert.isTrue(!rsocketStrategies.decoders().isEmpty(), "No decoders");
9299

93-
// 2. Application customizations
94-
this.factoryConfigurers.forEach(c -> c.accept(rsocketFactory));
100+
RSocketFactory.ClientRSocketFactory rsocketFactory = RSocketFactory.connect();
101+
MimeType dataMimeType = getDataMimeType(rsocketStrategies);
102+
rsocketFactory.dataMimeType(dataMimeType.toString());
103+
this.factoryConfigurers.forEach(consumer -> consumer.accept(rsocketFactory));
95104

96105
return rsocketFactory.transport(transport).start()
97106
.map(rsocket -> new DefaultRSocketRequester(rsocket, dataMimeType, rsocketStrategies));
@@ -109,18 +118,20 @@ private RSocketStrategies getRSocketStrategies() {
109118
}
110119
}
111120

112-
@Nullable
113-
private MimeType getDefaultDataMimeType(RSocketStrategies strategies) {
114-
return strategies.encoders().stream()
115-
.flatMap(encoder -> encoder.getEncodableMimeTypes().stream())
116-
.filter(MimeType::isConcrete)
117-
.findFirst()
118-
.orElseGet(() ->
121+
private MimeType getDataMimeType(RSocketStrategies strategies) {
122+
if (this.dataMimeType != null) {
123+
return this.dataMimeType;
124+
}
125+
return Stream
126+
.concat(
127+
strategies.encoders().stream()
128+
.flatMap(encoder -> encoder.getEncodableMimeTypes().stream()),
119129
strategies.decoders().stream()
120130
.flatMap(encoder -> encoder.getDecodableMimeTypes().stream())
121-
.filter(MimeType::isConcrete)
122-
.findFirst()
123-
.orElse(null));
131+
)
132+
.filter(MimeType::isConcrete)
133+
.findFirst()
134+
.orElseThrow(() -> new IllegalArgumentException("Failed to select data MimeType to use."));
124135
}
125136

126137
}

spring-messaging/src/main/java/org/springframework/messaging/rsocket/RSocketRequester.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,20 @@ static RSocketRequester create(RSocket rsocket, @Nullable MimeType dataMimeType,
106106
*/
107107
interface Builder {
108108

109+
/**
110+
* Configure the MimeType to use for payload data. This is set on the
111+
* {@code SETUP} frame for the whole connection.
112+
* <p>By default this is set to the first concrete MimeType supported
113+
* by the configured encoders and decoders.
114+
* @param mimeType the data MimeType to use
115+
*/
116+
RSocketRequester.Builder dataMimeType(MimeType mimeType);
117+
109118
/**
110119
* Configure the {@code ClientRSocketFactory}.
111-
* <p>Note there is typically no need to set a data MimeType explicitly.
112-
* By default a data MimeType is picked by taking the first concrete
113-
* MimeType supported by the configured encoders and decoders.
120+
* <p><strong>Note:</strong> Please, do not set the {@code dataMimeType}
121+
* directly on the underlying {@code RSocketFactory.ClientRSocketFactory},
122+
* and use {@link #dataMimeType(MimeType)} instead.
114123
* @param configurer the configurer to apply
115124
*/
116125
RSocketRequester.Builder rsocketFactory(Consumer<RSocketFactory.ClientRSocketFactory> configurer);

spring-messaging/src/test/java/org/springframework/messaging/rsocket/DefaultRSocketRequesterBuilderTests.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.messaging.rsocket;
1818

19+
import java.lang.reflect.Field;
1920
import java.util.function.Consumer;
2021

2122
import io.netty.buffer.ByteBuf;
@@ -28,6 +29,13 @@
2829
import reactor.core.publisher.Flux;
2930
import reactor.core.publisher.Mono;
3031

32+
import org.springframework.core.codec.CharSequenceEncoder;
33+
import org.springframework.core.codec.StringDecoder;
34+
import org.springframework.util.MimeType;
35+
import org.springframework.util.MimeTypeUtils;
36+
import org.springframework.util.ReflectionUtils;
37+
38+
import static org.assertj.core.api.Assertions.assertThat;
3139
import static org.mockito.ArgumentMatchers.any;
3240
import static org.mockito.ArgumentMatchers.anyInt;
3341
import static org.mockito.BDDMockito.given;
@@ -67,9 +75,14 @@ public void shouldApplyCustomizationsAtSubscription() {
6775
@Test
6876
@SuppressWarnings("unchecked")
6977
public void shouldApplyCustomizations() {
78+
RSocketStrategies strategies = RSocketStrategies.builder()
79+
.encoder(CharSequenceEncoder.allMimeTypes())
80+
.decoder(StringDecoder.allMimeTypes())
81+
.build();
7082
Consumer<RSocketFactory.ClientRSocketFactory> factoryConfigurer = mock(Consumer.class);
7183
Consumer<RSocketStrategies.Builder> strategiesConfigurer = mock(Consumer.class);
7284
RSocketRequester.builder()
85+
.rsocketStrategies(strategies)
7386
.rsocketFactory(factoryConfigurer)
7487
.rsocketStrategies(strategiesConfigurer)
7588
.connect(this.transport)
@@ -79,6 +92,25 @@ public void shouldApplyCustomizations() {
7992
verify(strategiesConfigurer).accept(any(RSocketStrategies.Builder.class));
8093
}
8194

95+
@Test
96+
public void dataMimeType() throws NoSuchFieldException {
97+
RSocketStrategies strategies = RSocketStrategies.builder()
98+
.encoder(CharSequenceEncoder.allMimeTypes())
99+
.decoder(StringDecoder.allMimeTypes())
100+
.build();
101+
102+
RSocketRequester requester = RSocketRequester.builder()
103+
.rsocketStrategies(strategies)
104+
.dataMimeType(MimeTypeUtils.APPLICATION_JSON)
105+
.connect(this.transport)
106+
.block();
107+
108+
Field field = DefaultRSocketRequester.class.getDeclaredField("dataMimeType");
109+
ReflectionUtils.makeAccessible(field);
110+
MimeType dataMimeType = (MimeType) ReflectionUtils.getField(field, requester);
111+
assertThat(dataMimeType).isEqualTo(MimeTypeUtils.APPLICATION_JSON);
112+
}
113+
82114

83115
static class MockConnection implements DuplexConnection {
84116

@@ -99,7 +131,6 @@ public Mono<Void> onClose() {
99131

100132
@Override
101133
public void dispose() {
102-
103134
}
104135
}
105136

0 commit comments

Comments
 (0)