Browse Source

Add dataMimeType to RSocketRequestBuilder

Closes gh-23012
pull/23057/head
Rossen Stoyanchev 7 years ago
parent
commit
eacc531cf7
  1. 2
      spring-messaging/spring-messaging.gradle
  2. 49
      spring-messaging/src/main/java/org/springframework/messaging/rsocket/DefaultRSocketRequesterBuilder.java
  3. 15
      spring-messaging/src/main/java/org/springframework/messaging/rsocket/RSocketRequester.java
  4. 33
      spring-messaging/src/test/java/org/springframework/messaging/rsocket/DefaultRSocketRequesterBuilderTests.java

2
spring-messaging/spring-messaging.gradle

@ -7,7 +7,7 @@ dependencyManagement {
} }
} }
def rsocketVersion = "0.12.2-RC3-SNAPSHOT" def rsocketVersion = "0.12.2-RC4-SNAPSHOT"
dependencies { dependencies {
compile(project(":spring-beans")) compile(project(":spring-beans"))

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

@ -20,6 +20,7 @@ import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Stream;
import io.rsocket.RSocketFactory; import io.rsocket.RSocketFactory;
import io.rsocket.transport.ClientTransport; import io.rsocket.transport.ClientTransport;
@ -28,6 +29,7 @@ import io.rsocket.transport.netty.client.WebsocketClientTransport;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.MimeType; import org.springframework.util.MimeType;
/** /**
@ -39,6 +41,9 @@ import org.springframework.util.MimeType;
*/ */
final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder { final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder {
@Nullable
private MimeType dataMimeType;
private List<Consumer<RSocketFactory.ClientRSocketFactory>> factoryConfigurers = new ArrayList<>(); private List<Consumer<RSocketFactory.ClientRSocketFactory>> factoryConfigurers = new ArrayList<>();
@Nullable @Nullable
@ -47,6 +52,12 @@ final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder {
private List<Consumer<RSocketStrategies.Builder>> strategiesConfigurers = new ArrayList<>(); private List<Consumer<RSocketStrategies.Builder>> strategiesConfigurers = new ArrayList<>();
@Override
public RSocketRequester.Builder dataMimeType(MimeType mimeType) {
this.dataMimeType = mimeType;
return this;
}
@Override @Override
public RSocketRequester.Builder rsocketFactory(Consumer<RSocketFactory.ClientRSocketFactory> configurer) { public RSocketRequester.Builder rsocketFactory(Consumer<RSocketFactory.ClientRSocketFactory> configurer) {
this.factoryConfigurers.add(configurer); this.factoryConfigurers.add(configurer);
@ -81,17 +92,15 @@ final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder {
} }
private Mono<RSocketRequester> doConnect(ClientTransport transport) { private Mono<RSocketRequester> doConnect(ClientTransport transport) {
RSocketStrategies rsocketStrategies = getRSocketStrategies();
RSocketFactory.ClientRSocketFactory rsocketFactory = RSocketFactory.connect();
// 1. Apply default settings RSocketStrategies rsocketStrategies = getRSocketStrategies();
MimeType dataMimeType = getDefaultDataMimeType(rsocketStrategies); Assert.isTrue(!rsocketStrategies.encoders().isEmpty(), "No encoders");
if (dataMimeType != null) { Assert.isTrue(!rsocketStrategies.decoders().isEmpty(), "No decoders");
rsocketFactory.dataMimeType(dataMimeType.toString());
}
// 2. Application customizations RSocketFactory.ClientRSocketFactory rsocketFactory = RSocketFactory.connect();
this.factoryConfigurers.forEach(c -> c.accept(rsocketFactory)); MimeType dataMimeType = getDataMimeType(rsocketStrategies);
rsocketFactory.dataMimeType(dataMimeType.toString());
this.factoryConfigurers.forEach(consumer -> consumer.accept(rsocketFactory));
return rsocketFactory.transport(transport).start() return rsocketFactory.transport(transport).start()
.map(rsocket -> new DefaultRSocketRequester(rsocket, dataMimeType, rsocketStrategies)); .map(rsocket -> new DefaultRSocketRequester(rsocket, dataMimeType, rsocketStrategies));
@ -109,18 +118,20 @@ final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder {
} }
} }
@Nullable private MimeType getDataMimeType(RSocketStrategies strategies) {
private MimeType getDefaultDataMimeType(RSocketStrategies strategies) { if (this.dataMimeType != null) {
return strategies.encoders().stream() return this.dataMimeType;
.flatMap(encoder -> encoder.getEncodableMimeTypes().stream()) }
.filter(MimeType::isConcrete) return Stream
.findFirst() .concat(
.orElseGet(() -> strategies.encoders().stream()
.flatMap(encoder -> encoder.getEncodableMimeTypes().stream()),
strategies.decoders().stream() strategies.decoders().stream()
.flatMap(encoder -> encoder.getDecodableMimeTypes().stream()) .flatMap(encoder -> encoder.getDecodableMimeTypes().stream())
.filter(MimeType::isConcrete) )
.findFirst() .filter(MimeType::isConcrete)
.orElse(null)); .findFirst()
.orElseThrow(() -> new IllegalArgumentException("Failed to select data MimeType to use."));
} }
} }

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

@ -106,11 +106,20 @@ public interface RSocketRequester {
*/ */
interface Builder { interface Builder {
/**
* Configure the MimeType to use for payload data. This is set on the
* {@code SETUP} frame for the whole connection.
* <p>By default this is set to the first concrete MimeType supported
* by the configured encoders and decoders.
* @param mimeType the data MimeType to use
*/
RSocketRequester.Builder dataMimeType(MimeType mimeType);
/** /**
* Configure the {@code ClientRSocketFactory}. * Configure the {@code ClientRSocketFactory}.
* <p>Note there is typically no need to set a data MimeType explicitly. * <p><strong>Note:</strong> Please, do not set the {@code dataMimeType}
* By default a data MimeType is picked by taking the first concrete * directly on the underlying {@code RSocketFactory.ClientRSocketFactory},
* MimeType supported by the configured encoders and decoders. * and use {@link #dataMimeType(MimeType)} instead.
* @param configurer the configurer to apply * @param configurer the configurer to apply
*/ */
RSocketRequester.Builder rsocketFactory(Consumer<RSocketFactory.ClientRSocketFactory> configurer); RSocketRequester.Builder rsocketFactory(Consumer<RSocketFactory.ClientRSocketFactory> configurer);

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

@ -16,6 +16,7 @@
package org.springframework.messaging.rsocket; package org.springframework.messaging.rsocket;
import java.lang.reflect.Field;
import java.util.function.Consumer; import java.util.function.Consumer;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
@ -28,6 +29,13 @@ import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.core.codec.CharSequenceEncoder;
import org.springframework.core.codec.StringDecoder;
import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
import org.springframework.util.ReflectionUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
@ -67,9 +75,14 @@ public class DefaultRSocketRequesterBuilderTests {
@Test @Test
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void shouldApplyCustomizations() { public void shouldApplyCustomizations() {
RSocketStrategies strategies = RSocketStrategies.builder()
.encoder(CharSequenceEncoder.allMimeTypes())
.decoder(StringDecoder.allMimeTypes())
.build();
Consumer<RSocketFactory.ClientRSocketFactory> factoryConfigurer = mock(Consumer.class); Consumer<RSocketFactory.ClientRSocketFactory> factoryConfigurer = mock(Consumer.class);
Consumer<RSocketStrategies.Builder> strategiesConfigurer = mock(Consumer.class); Consumer<RSocketStrategies.Builder> strategiesConfigurer = mock(Consumer.class);
RSocketRequester.builder() RSocketRequester.builder()
.rsocketStrategies(strategies)
.rsocketFactory(factoryConfigurer) .rsocketFactory(factoryConfigurer)
.rsocketStrategies(strategiesConfigurer) .rsocketStrategies(strategiesConfigurer)
.connect(this.transport) .connect(this.transport)
@ -79,6 +92,25 @@ public class DefaultRSocketRequesterBuilderTests {
verify(strategiesConfigurer).accept(any(RSocketStrategies.Builder.class)); verify(strategiesConfigurer).accept(any(RSocketStrategies.Builder.class));
} }
@Test
public void dataMimeType() throws NoSuchFieldException {
RSocketStrategies strategies = RSocketStrategies.builder()
.encoder(CharSequenceEncoder.allMimeTypes())
.decoder(StringDecoder.allMimeTypes())
.build();
RSocketRequester requester = RSocketRequester.builder()
.rsocketStrategies(strategies)
.dataMimeType(MimeTypeUtils.APPLICATION_JSON)
.connect(this.transport)
.block();
Field field = DefaultRSocketRequester.class.getDeclaredField("dataMimeType");
ReflectionUtils.makeAccessible(field);
MimeType dataMimeType = (MimeType) ReflectionUtils.getField(field, requester);
assertThat(dataMimeType).isEqualTo(MimeTypeUtils.APPLICATION_JSON);
}
static class MockConnection implements DuplexConnection { static class MockConnection implements DuplexConnection {
@ -99,7 +131,6 @@ public class DefaultRSocketRequesterBuilderTests {
@Override @Override
public void dispose() { public void dispose() {
} }
} }

Loading…
Cancel
Save