RSocket Metadata - custom object

876 views Asked by At

I am playing with rsocket-java.

Is there any way to send custom object via metadata.?

I saw this code sample in their documenation.

RSocketStrategies strategies = RSocketStrategies.builder()
    .metadataExtractorRegistry(registry -> {
        registry.metadataToExtract(fooMimeType, Foo.class, "foo");
        // ...
    })
    .build();
 return strategies;

I tried something similar.

@Bean
public RSocketStrategies strategies(){

    RSocketStrategies strategies = RSocketStrategies.builder()
        .metadataExtractorRegistry(registry -> {
            registry.metadataToExtract(someMimeType, Something.class, "something");
            // ...
        })
        .build();
     return strategies;

}

but getting this exception.

Caused by: java.lang.IllegalArgumentException: No decoder for messaging/x.something and com.demo.Something

Should I create my own decoder for each and every object type?

Please do not show String examples. Question is for passing custom objects.

2

There are 2 answers

1
Yuri Schimke On

You should be registering this bean somewhere, see https://docs.spring.io/spring-integration/docs/current/reference/html/rsocket.html

@Bean
public RSocketStrategies rsocketStrategies() {
    return RSocketStrategies.builder()
        .decoder(StringDecoder.textPlainOnly())
        .encoder(CharSequenceEncoder.allMimeTypes())
        .dataBufferFactory(new DefaultDataBufferFactory(true))
        .build();
}

@Bean
public ServerRSocketConnector serverRSocketConnector() {
    ServerRSocketConnector serverRSocketConnector = new ServerRSocketConnector("localhost", 0);
    serverRSocketConnector.setRSocketStrategies(rsocketStrategies());
    serverRSocketConnector.setMetadataMimeType(new MimeType("message", "x.rsocket.routing.v0"));
    serverRSocketConnector.setServerConfigurer((server) -> server.payloadDecoder(PayloadDecoder.ZERO_COPY));
    serverRSocketConnector.setClientRSocketKeyStrategy((headers, data) -> ""
                                    + headers.get(DestinationPatternsMessageCondition.LOOKUP_DESTINATION_HEADER));
    return serverRSocketConnector;
}

But it isn't possible to answer with just the minimal snippet you have provided. Can you provide a runnable example or more context in your example?

0
Kalin Muzdrakov On

You need to define your MimeType like that:

public static final String FOO_HEADER = "foo-header";
public static final MimeType FOO_MYME_TYPE = MimeType.valueOf("application/json");

Then in your RSocket strategies configuration

@Bean
RSocketStrategiesCustomizer rSocketStrategiesCustomizer() {
    return strategies -> strategies.metadataExtractorRegistry(r -> r.metadataToExtract(Constants.FOO_MYME_TYPE, Foo.class, Constants.FOO_HEADER))
                                   .decoder(new Jackson2JsonDecoder())
                                   .encoder(new Jackson2JsonEncoder());

}

Pass the metadata object in you RSocketRequester:

getRequester().route(path).metadata(userToken, Constants.FOO_MYME_TYPE).data(fooRequest.getPayload.retrieveFlux(FooResponse.class))

Finally you can expect the metadata at your endpoint

@Headers Map<String, Object> metadata

or explicitly:

@Header(Constants.FOO_HEADER) Foo fooData