Requesters must interpret the metadata. Composite metadata allows metadata values to be independently formatted (for example, for routing, for security purposes, tracing), each of which has its own MIME type. Applications need a way to configure MIME metadata types to support them, as well as a way to access the extracted values.

MetadataExtractor is a contract for obtaining serialized metadata and returning decoded name-value pairs, which can then be accessed as headers by name, for example via the @Header in annotated handler methods.

A DefaultMetadataExtractor can be passed to Decoder instances to decode metadata. Out of the box it has built-in support for "message/x.rsocket.routing. v0", which is decoded into a String and stored with the key "route". For any other MIME type, you must specify a Decoder and register the MIME type as follows:

Java
DefaultMetadataExtractor extractor = new DefaultMetadataExtractor(metadataDecoders);
extractor.metadataToExtract(fooMimeType, Foo.class, "foo");
Kotlin
import org.springframework.messaging.rsocket.metadataToExtract
val extractor = DefaultMetadataExtractor(metadataDecoders)
extractor.metadataToExtract<Foo>(fooMimeType, "foo")

Composite metadata is good for combining independent metadata values. However, the requester may not support or use composite metadata. In this case, DefaultMetadataExtractor may require custom logic to display the decoded value in the output Map. Here's an example that uses JSON for metadata:

Java
DefaultMetadataExtractor extractor = new DefaultMetadataExtractor(metadataDecoders);
extractor.metadataToExtract(
MimeType.valueOf("application/vnd.myapp.metadata+json"),
new ParameterizedTypeReference<Map<String,String>>() {},
(jsonMap, outputMap) -> {
outputMap.putAll(jsonMap);
});
Kotlin
import org.springframework.messaging.rsocket.metadataToExtract
val extractor = DefaultMetadataExtractor(metadataDecoders)
extractor.metadataToExtract<Map<String, String>>(MimeType.valueOf("application/vnd.myapp.metadata+json")) { jsonMap, outputMap -> ;
outputMap.putAll(jsonMap)
}

When configuring a MetadataExtractor via RSocketStrategies, you can let RSocketStrategies.Builder create the extractor with the decoders configured and simply use the callback to configure the registration routines as follows :

Java
RSocketStrategies strategies = RSocketStrategies.builder()
.metadataExtractorRegistry(registry -> {
registry.metadataToExtract(fooMimeType, Foo.class, "foo");
// ...
})
.build();
Kotlin
import org.springframework.messaging.rsocket.metadataToExtract
val strategies = RSocketStrategies.builder()
.metadataExtractorRegistry { registry: MetadataExtractorRegistry ->
    registry.metadataToExtract<Foo>(fooMimeType, "foo")
    // ...
}
.build()