Browse Source

Remove RSocket metadata MimeType constants

For public use, these constants aren't ideally exposed through an SPI
like MetadataExtractor, and there isn't any other obvious place either.
In practice the only public API where these can be passed in is
RSocketRequester and RSocketMessageHandler both of which already
default to composite metadata anyway, leaving only the routing MimeType
to be used potentially but much less likely.
Due to existence of similar constants in the RSocket itself, i.e.
WellKnownMimeType, we can get by internally too without declaring
MimeType constants from a central place.
pull/23530/head
Rossen Stoyanchev 5 years ago
parent
commit
29a58ab045
  1. 5
      spring-messaging/src/main/java/org/springframework/messaging/rsocket/DefaultMetadataExtractor.java
  2. 20
      spring-messaging/src/main/java/org/springframework/messaging/rsocket/DefaultRSocketRequesterBuilder.java
  3. 46
      spring-messaging/src/main/java/org/springframework/messaging/rsocket/MetadataEncoder.java
  4. 10
      spring-messaging/src/main/java/org/springframework/messaging/rsocket/MetadataExtractor.java
  5. 4
      spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/RSocketMessageHandler.java
  6. 14
      spring-messaging/src/test/java/org/springframework/messaging/rsocket/DefaultMetadataExtractorTests.java
  7. 3
      spring-messaging/src/test/java/org/springframework/messaging/rsocket/DefaultRSocketRequesterBuilderTests.java
  8. 24
      spring-messaging/src/test/java/org/springframework/messaging/rsocket/MetadataEncoderTests.java

5
spring-messaging/src/main/java/org/springframework/messaging/rsocket/DefaultMetadataExtractor.java

@ -28,6 +28,7 @@ import io.netty.buffer.ByteBuf; @@ -28,6 +28,7 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.rsocket.Payload;
import io.rsocket.metadata.CompositeMetadata;
import io.rsocket.metadata.WellKnownMimeType;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.ResolvableType;
@ -153,7 +154,7 @@ public class DefaultMetadataExtractor implements MetadataExtractor { @@ -153,7 +154,7 @@ public class DefaultMetadataExtractor implements MetadataExtractor {
@Override
public Map<String, Object> extract(Payload payload, MimeType metadataMimeType) {
Map<String, Object> result = new HashMap<>();
if (metadataMimeType.equals(COMPOSITE_METADATA)) {
if (metadataMimeType.toString().equals(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.toString())) {
for (CompositeMetadata.Entry entry : new CompositeMetadata(payload.metadata(), false)) {
extractEntry(entry.getContent(), entry.getMimeType(), result);
}
@ -170,7 +171,7 @@ public class DefaultMetadataExtractor implements MetadataExtractor { @@ -170,7 +171,7 @@ public class DefaultMetadataExtractor implements MetadataExtractor {
extractor.extract(content, result);
return;
}
if (MetadataExtractor.ROUTING.toString().equals(mimeType)) {
if (mimeType != null && mimeType.equals(WellKnownMimeType.MESSAGE_RSOCKET_ROUTING.getString())) {
// TODO: use rsocket-core API when available
result.put(MetadataExtractor.ROUTE_KEY, content.toString(StandardCharsets.UTF_8));
}

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

@ -27,6 +27,7 @@ import java.util.function.Consumer; @@ -27,6 +27,7 @@ import java.util.function.Consumer;
import io.rsocket.Payload;
import io.rsocket.RSocketFactory;
import io.rsocket.frame.decoder.PayloadDecoder;
import io.rsocket.metadata.WellKnownMimeType;
import io.rsocket.transport.ClientTransport;
import io.rsocket.transport.netty.client.TcpClientTransport;
import io.rsocket.transport.netty.client.WebsocketClientTransport;
@ -43,6 +44,7 @@ import org.springframework.lang.Nullable; @@ -43,6 +44,7 @@ import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
/**
* Default implementation of {@link RSocketRequester.Builder}.
@ -59,7 +61,8 @@ final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder { @@ -59,7 +61,8 @@ final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder {
@Nullable
private MimeType dataMimeType;
private MimeType metadataMimeType = MetadataExtractor.COMPOSITE_METADATA;
@Nullable
private MimeType metadataMimeType;
@Nullable
private Object setupData;
@ -159,11 +162,14 @@ final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder { @@ -159,11 +162,14 @@ final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder {
factory.frameDecoder(PayloadDecoder.ZERO_COPY);
}
MimeType metaMimeType = this.metadataMimeType != null ? this.metadataMimeType :
MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
MimeType dataMimeType = getDataMimeType(rsocketStrategies);
factory.dataMimeType(dataMimeType.toString());
factory.metadataMimeType(this.metadataMimeType.toString());
factory.metadataMimeType(metaMimeType.toString());
Payload setupPayload = getSetupPayload(dataMimeType, rsocketStrategies);
Payload setupPayload = getSetupPayload(dataMimeType, metaMimeType, rsocketStrategies);
if (setupPayload != null) {
factory.setupPayload(setupPayload);
}
@ -171,14 +177,14 @@ final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder { @@ -171,14 +177,14 @@ final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder {
return factory.transport(transport)
.start()
.map(rsocket -> new DefaultRSocketRequester(
rsocket, dataMimeType, this.metadataMimeType, rsocketStrategies));
rsocket, dataMimeType, metaMimeType, rsocketStrategies));
}
@Nullable
private Payload getSetupPayload(MimeType dataMimeType, RSocketStrategies strategies) {
private Payload getSetupPayload(MimeType dataMimeType, MimeType metaMimeType, RSocketStrategies strategies) {
DataBuffer metadata = null;
if (this.setupRoute != null || !CollectionUtils.isEmpty(this.setupMetadata)) {
metadata = new MetadataEncoder(this.metadataMimeType, strategies)
metadata = new MetadataEncoder(metaMimeType, strategies)
.metadataAndOrRoute(this.setupMetadata, this.setupRoute, this.setupRouteVars)
.encode();
}
@ -246,7 +252,7 @@ final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder { @@ -246,7 +252,7 @@ final class DefaultRSocketRequesterBuilder implements RSocketRequester.Builder {
private static MimeType getMimeType(Decoder<?> decoder) {
MimeType mimeType = decoder.getDecodableMimeTypes().get(0);
return new MimeType(mimeType, Collections.emptyMap());
return mimeType.getParameters().isEmpty() ? mimeType : new MimeType(mimeType, Collections.emptyMap());
}
}

46
spring-messaging/src/main/java/org/springframework/messaging/rsocket/MetadataEncoder.java

@ -25,6 +25,7 @@ import java.util.regex.Pattern; @@ -25,6 +25,7 @@ import java.util.regex.Pattern;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.CompositeByteBuf;
import io.rsocket.metadata.CompositeMetadataFlyweight;
import io.rsocket.metadata.WellKnownMimeType;
import org.springframework.core.ResolvableType;
import org.springframework.core.codec.Encoder;
@ -46,7 +47,7 @@ import org.springframework.util.ObjectUtils; @@ -46,7 +47,7 @@ import org.springframework.util.ObjectUtils;
final class MetadataEncoder {
/** For route variable replacement. */
private static final Pattern VARS_PATTERN = Pattern.compile("\\{([^/]+?)\\}");
private static final Pattern VARS_PATTERN = Pattern.compile("\\{([^/]+?)}");
private final MimeType metadataMimeType;
@ -68,7 +69,8 @@ final class MetadataEncoder { @@ -68,7 +69,8 @@ final class MetadataEncoder {
Assert.notNull(strategies, "RSocketStrategies is required");
this.metadataMimeType = metadataMimeType;
this.strategies = strategies;
this.isComposite = metadataMimeType.equals(MetadataExtractor.COMPOSITE_METADATA);
this.isComposite = this.metadataMimeType.toString().equals(
WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
this.allocator = bufferFactory() instanceof NettyDataBufferFactory ?
((NettyDataBufferFactory) bufferFactory()).getByteBufAllocator() : ByteBufAllocator.DEFAULT;
}
@ -157,11 +159,15 @@ final class MetadataEncoder { @@ -157,11 +159,15 @@ final class MetadataEncoder {
* @see PayloadUtils#createPayload(DataBuffer, DataBuffer)
*/
public DataBuffer encode() {
Map<Object, MimeType> mergedMetadata = mergeRouteAndMetadata();
if (this.isComposite) {
CompositeByteBuf composite = this.allocator.compositeBuffer();
if (this.route != null) {
CompositeMetadataFlyweight.encodeAndAddMetadata(composite, this.allocator,
WellKnownMimeType.MESSAGE_RSOCKET_ROUTING,
PayloadUtils.asByteBuf(bufferFactory().wrap(this.route.getBytes(StandardCharsets.UTF_8))));
}
try {
mergedMetadata.forEach((value, mimeType) -> {
this.metadata.forEach((value, mimeType) -> {
DataBuffer buffer = encodeEntry(value, mimeType);
CompositeMetadataFlyweight.encodeAndAddMetadata(
composite, this.allocator, mimeType.toString(), PayloadUtils.asByteBuf(buffer));
@ -180,38 +186,24 @@ final class MetadataEncoder { @@ -180,38 +186,24 @@ final class MetadataEncoder {
throw ex;
}
}
else if (this.route != null) {
Assert.isTrue(this.metadata.isEmpty(), "Composite metadata required for route and other entries");
return this.metadataMimeType.toString().equals(WellKnownMimeType.MESSAGE_RSOCKET_ROUTING.getString()) ?
bufferFactory().wrap(this.route.getBytes(StandardCharsets.UTF_8)) :
encodeEntry(this.route, this.metadataMimeType);
}
else {
Assert.isTrue(mergedMetadata.size() == 1, "Composite metadata required for multiple entries");
Map.Entry<Object, MimeType> entry = mergedMetadata.entrySet().iterator().next();
Assert.isTrue(this.metadata.size() == 1, "Composite metadata required for multiple entries");
Map.Entry<Object, MimeType> entry = this.metadata.entrySet().iterator().next();
if (!this.metadataMimeType.equals(entry.getValue())) {
throw new IllegalArgumentException(
"Connection configured for metadata mime type " +
"'" + this.metadataMimeType + "', but actual is `" + mergedMetadata + "`");
"'" + this.metadataMimeType + "', but actual is `" + this.metadata + "`");
}
return encodeEntry(entry.getKey(), entry.getValue());
}
}
private Map<Object, MimeType> mergeRouteAndMetadata() {
if (this.route == null) {
return this.metadata;
}
MimeType routeMimeType = this.metadataMimeType.equals(MetadataExtractor.COMPOSITE_METADATA) ?
MetadataExtractor.ROUTING : this.metadataMimeType;
Object routeValue = this.route;
if (routeMimeType.equals(MetadataExtractor.ROUTING)) {
// TODO: use rsocket-core API when available
routeValue = bufferFactory().wrap(this.route.getBytes(StandardCharsets.UTF_8));
}
Map<Object, MimeType> result = new LinkedHashMap<>();
result.put(routeValue, routeMimeType);
result.putAll(this.metadata);
return result;
}
@SuppressWarnings("unchecked")
private <T> DataBuffer encodeEntry(Object metadata, MimeType mimeType) {
if (metadata instanceof DataBuffer) {

10
spring-messaging/src/main/java/org/springframework/messaging/rsocket/MetadataExtractor.java

@ -38,16 +38,6 @@ public interface MetadataExtractor { @@ -38,16 +38,6 @@ public interface MetadataExtractor {
*/
String ROUTE_KEY = "route";
/**
* Constant MimeType {@code "message/x.rsocket.composite-metadata.v0"}.
*/
MimeType COMPOSITE_METADATA = new MimeType("message", "x.rsocket.composite-metadata.v0");
/**
* Constant for MimeType {@code "message/x.rsocket.routing.v0"}.
*/
MimeType ROUTING = new MimeType("message", "x.rsocket.routing.v0");
/**
* Extract a map of values from the given {@link Payload} metadata.

4
spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/RSocketMessageHandler.java

@ -24,6 +24,7 @@ import io.rsocket.ConnectionSetupPayload; @@ -24,6 +24,7 @@ import io.rsocket.ConnectionSetupPayload;
import io.rsocket.RSocket;
import io.rsocket.SocketAcceptor;
import io.rsocket.frame.FrameType;
import io.rsocket.metadata.WellKnownMimeType;
import reactor.core.publisher.Mono;
import org.springframework.beans.BeanUtils;
@ -73,7 +74,8 @@ public class RSocketMessageHandler extends MessageMappingMessageHandler { @@ -73,7 +74,8 @@ public class RSocketMessageHandler extends MessageMappingMessageHandler {
@Nullable
private MimeType defaultDataMimeType;
private MimeType defaultMetadataMimeType = MetadataExtractor.COMPOSITE_METADATA;
private MimeType defaultMetadataMimeType = MimeTypeUtils.parseMimeType(
WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
public RSocketMessageHandler() {

14
spring-messaging/src/test/java/org/springframework/messaging/rsocket/DefaultMetadataExtractorTests.java

@ -21,6 +21,7 @@ import java.util.Map; @@ -21,6 +21,7 @@ import java.util.Map;
import io.netty.buffer.PooledByteBufAllocator;
import io.rsocket.Payload;
import io.rsocket.metadata.WellKnownMimeType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -30,12 +31,12 @@ import org.springframework.core.codec.StringDecoder; @@ -30,12 +31,12 @@ import org.springframework.core.codec.StringDecoder;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.util.Assert;
import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.springframework.messaging.rsocket.MetadataExtractor.COMPOSITE_METADATA;
import static org.springframework.messaging.rsocket.MetadataExtractor.ROUTE_KEY;
import static org.springframework.messaging.rsocket.MetadataExtractor.ROUTING;
import static org.springframework.util.MimeTypeUtils.TEXT_HTML;
import static org.springframework.util.MimeTypeUtils.TEXT_PLAIN;
import static org.springframework.util.MimeTypeUtils.TEXT_XML;
@ -47,6 +48,10 @@ import static org.springframework.util.MimeTypeUtils.TEXT_XML; @@ -47,6 +48,10 @@ import static org.springframework.util.MimeTypeUtils.TEXT_XML;
*/
public class DefaultMetadataExtractorTests {
private static MimeType COMPOSITE_METADATA =
MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
private RSocketStrategies strategies;
private DefaultMetadataExtractor extractor;
@ -108,10 +113,11 @@ public class DefaultMetadataExtractorTests { @@ -108,10 +113,11 @@ public class DefaultMetadataExtractorTests {
@Test
public void route() {
MetadataEncoder metadataEncoder = new MetadataEncoder(ROUTING, this.strategies).route("toA");
MimeType metaMimeType = MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_ROUTING.getString());
MetadataEncoder metadataEncoder = new MetadataEncoder(metaMimeType, this.strategies).route("toA");
DataBuffer metadata = metadataEncoder.encode();
Payload payload = createPayload(metadata);
Map<String, Object> result = this.extractor.extract(payload, ROUTING);
Map<String, Object> result = this.extractor.extract(payload, metaMimeType);
payload.release();
assertThat(result).hasSize(1).containsEntry(ROUTE_KEY, "toA");

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

@ -28,6 +28,7 @@ import io.rsocket.ConnectionSetupPayload; @@ -28,6 +28,7 @@ import io.rsocket.ConnectionSetupPayload;
import io.rsocket.DuplexConnection;
import io.rsocket.RSocketFactory;
import io.rsocket.frame.decoder.PayloadDecoder;
import io.rsocket.metadata.WellKnownMimeType;
import io.rsocket.transport.ClientTransport;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -150,7 +151,7 @@ public class DefaultRSocketRequesterBuilderTests { @@ -150,7 +151,7 @@ public class DefaultRSocketRequesterBuilderTests {
@Test
public void mimeTypesCannotBeChangedAtRSocketFactoryLevel() {
MimeType dataMimeType = MimeTypeUtils.APPLICATION_JSON;
MimeType metaMimeType = MetadataExtractor.ROUTING;
MimeType metaMimeType = MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_ROUTING.getString());
RSocketRequester requester = RSocketRequester.builder()
.metadataMimeType(metaMimeType)

24
spring-messaging/src/test/java/org/springframework/messaging/rsocket/MetadataEncoderTests.java

@ -23,6 +23,7 @@ import java.util.Map; @@ -23,6 +23,7 @@ import java.util.Map;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.rsocket.metadata.CompositeMetadata;
import io.rsocket.metadata.WellKnownMimeType;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.buffer.DataBuffer;
@ -43,12 +44,16 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -43,12 +44,16 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
*/
public class MetadataEncoderTests {
private static MimeType COMPOSITE_METADATA =
MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString());
private final RSocketStrategies strategies = RSocketStrategies.create();
@Test
public void compositeMetadataWithRoute() {
DataBuffer buffer = new MetadataEncoder(MetadataExtractor.COMPOSITE_METADATA, this.strategies)
DataBuffer buffer = new MetadataEncoder(COMPOSITE_METADATA, this.strategies)
.route("toA")
.encode();
@ -57,7 +62,7 @@ public class MetadataEncoderTests { @@ -57,7 +62,7 @@ public class MetadataEncoderTests {
assertThat(iterator.hasNext()).isTrue();
CompositeMetadata.Entry entry = iterator.next();
assertThat(entry.getMimeType()).isEqualTo(MetadataExtractor.ROUTING.toString());
assertThat(entry.getMimeType()).isEqualTo(WellKnownMimeType.MESSAGE_RSOCKET_ROUTING.getString());
assertThat(entry.getContent().toString(StandardCharsets.UTF_8)).isEqualTo("toA");
assertThat(iterator.hasNext()).isFalse();
@ -66,7 +71,7 @@ public class MetadataEncoderTests { @@ -66,7 +71,7 @@ public class MetadataEncoderTests {
@Test
public void compositeMetadataWithRouteAndText() {
DataBuffer buffer = new MetadataEncoder(MetadataExtractor.COMPOSITE_METADATA, this.strategies)
DataBuffer buffer = new MetadataEncoder(COMPOSITE_METADATA, this.strategies)
.route("toA")
.metadata("My metadata", MimeTypeUtils.TEXT_PLAIN)
.encode();
@ -76,7 +81,7 @@ public class MetadataEncoderTests { @@ -76,7 +81,7 @@ public class MetadataEncoderTests {
assertThat(iterator.hasNext()).isTrue();
CompositeMetadata.Entry entry = iterator.next();
assertThat(entry.getMimeType()).isEqualTo(MetadataExtractor.ROUTING.toString());
assertThat(entry.getMimeType()).isEqualTo(WellKnownMimeType.MESSAGE_RSOCKET_ROUTING.getString());
assertThat(entry.getContent().toString(StandardCharsets.UTF_8)).isEqualTo("toA");
assertThat(iterator.hasNext()).isTrue();
@ -89,8 +94,11 @@ public class MetadataEncoderTests { @@ -89,8 +94,11 @@ public class MetadataEncoderTests {
@Test
public void routeWithRoutingMimeType() {
MimeType metaMimeType = MimeTypeUtils.parseMimeType(
WellKnownMimeType.MESSAGE_RSOCKET_ROUTING.getString());
DataBuffer buffer =
new MetadataEncoder(MetadataExtractor.ROUTING, this.strategies)
new MetadataEncoder(metaMimeType, this.strategies)
.route("toA")
.encode();
@ -154,7 +162,7 @@ public class MetadataEncoderTests { @@ -154,7 +162,7 @@ public class MetadataEncoderTests {
@Test
public void mimeTypeRequiredForCompositeEntries() {
MetadataEncoder encoder = new MetadataEncoder(MetadataExtractor.COMPOSITE_METADATA, this.strategies);
MetadataEncoder encoder = new MetadataEncoder(COMPOSITE_METADATA, this.strategies);
assertThatThrownBy(() -> encoder.metadata("toA", null))
.hasMessage("MimeType is required for composite metadata entries.");
@ -174,7 +182,7 @@ public class MetadataEncoderTests { @@ -174,7 +182,7 @@ public class MetadataEncoderTests {
DefaultDataBufferFactory bufferFactory = new DefaultDataBufferFactory();
RSocketStrategies strategies = RSocketStrategies.builder().dataBufferFactory(bufferFactory).build();
DataBuffer buffer = new MetadataEncoder(MetadataExtractor.COMPOSITE_METADATA, strategies)
DataBuffer buffer = new MetadataEncoder(COMPOSITE_METADATA, strategies)
.route("toA")
.encode();
@ -187,7 +195,7 @@ public class MetadataEncoderTests { @@ -187,7 +195,7 @@ public class MetadataEncoderTests {
assertThat(iterator.hasNext()).isTrue();
CompositeMetadata.Entry entry = iterator.next();
assertThat(entry.getMimeType()).isEqualTo(MetadataExtractor.ROUTING.toString());
assertThat(entry.getMimeType()).isEqualTo(WellKnownMimeType.MESSAGE_RSOCKET_ROUTING.getString());
assertThat(entry.getContent().toString(StandardCharsets.UTF_8)).isEqualTo("toA");
assertThat(iterator.hasNext()).isFalse();

Loading…
Cancel
Save