Reputation: 10004
Trying to use Protobuf with RSocket, Requester doesn't consider dataMimeType
set to application/protobuf
or application/vnd.google.protobuf
. I get error No decoder
Client Application
@SpringBootApplication
@Slf4j
public class PersonServiceClientApplication {
@Bean
RSocketRequester rSocketRequester(RSocketStrategies rSocketStrategies) {
return RSocketRequester.builder()
.rsocketFactory(
factory -> factory.dataMimeType("application/protobuf").frameDecoder(PayloadDecoder.ZERO_COPY))
.rsocketStrategies(rSocketStrategies).connectTcp("localhost", 9080).retry().block();
}
@Bean
public RSocketStrategiesCustomizer protobufRSocketStrategyCustomizer() {
return (strategy) -> {
strategy.decoder(new ProtobufDecoder());
strategy.encoder(new ProtobufEncoder());
};
}
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(PersonServiceClientApplication.class, args);
RSocketRequester req = context.getBean(RSocketRequester.class);
req.route("io.github.kprasad99.person.get3").retrieveMono(Person.class)
.doOnNext(e -> log.info(e.getFirstName())).block(Duration.ofSeconds(30));
}
}
Stacktrace
Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.IllegalArgumentException: No decoder for io.github.kprasad.person.proto.PersonProto$Person
at org.springframework.messaging.rsocket.RSocketStrategies.decoder(RSocketStrategies.java:92)
at org.springframework.messaging.rsocket.DefaultRSocketRequester$DefaultRequestSpec.retrieveMono(DefaultRSocketRequester.java:274)
at org.springframework.messaging.rsocket.DefaultRSocketRequester$DefaultRequestSpec.retrieveMono(DefaultRSocketRequester.java:258)
at io.github.kprasad99.person.PersonServiceClientApplication.main(PersonServiceClientApplication.java:69)
... 5 more
However if I explicitly disable RSocketStrategiesAutoConfiguration
, and recreate RSocketStrategies
bean, it works.
SpringBootApplication(exclude = { RSocketStrategiesAutoConfiguration.class })
@Slf4j
public class PersonServiceClientApplication {
private static final String PATHPATTERN_ROUTEMATCHER_CLASS = "org.springframework.web.util.pattern.PathPatternRouteMatcher";
@Bean
public RSocketStrategies rSocketStrategies(ObjectProvider<RSocketStrategiesCustomizer> customizers) {
RSocketStrategies.Builder builder = RSocketStrategies.builder();
if (ClassUtils.isPresent(PATHPATTERN_ROUTEMATCHER_CLASS, null)) {
builder.routeMatcher(new PathPatternRouteMatcher());
}
customizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
return builder.build();
}
@Bean
RSocketRequester rSocketRequester(RSocketStrategies rSocketStrategies) {
return RSocketRequester.builder()
.rsocketFactory(
factory -> factory.dataMimeType("application/protobuf").frameDecoder(PayloadDecoder.ZERO_COPY))
.rsocketStrategies(rSocketStrategies).connectTcp("localhost", 9080).retry().block();
}
@Bean
public RSocketStrategiesCustomizer protobufRSocketStrategyCustomizer() {
return (strategy) -> {
strategy.decoder(new ProtobufDecoder());
strategy.encoder(new ProtobufEncoder());
};
}
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(PersonServiceClientApplication.class, args);
RSocketRequester req = context.getBean(RSocketRequester.class);
req.route("io.github.kprasad99.person.get3").retrieveMono(Person.class)
.doOnNext(e -> log.info(e.getFirstName())).block(Duration.ofSeconds(30));
}
}
Why neither dataMimeType
nor protobufRSocketStrategyCustomizer
bean considered why decoding.
Upvotes: 1
Views: 1562
Reputation: 10004
Able to solve this, needed use application/x-protobuf
. Below is the beans created for client.
@Bean
public Mono<RSocketRequester> rSocketRequester(
RSocketRequester.Builder rsocketRequesterBuilder, ClientTransport clientTransport,
RSocketStrategies strategies) {
Mono<RSocketRequester> rsocketRequester = rsocketRequesterBuilder.rsocketStrategies(strategies)
.dataMimeType(new MimeType("application", "x-protobuf"))
.connect(clientTransport).log();
return rsocketRequester;
}
@Bean
public RSocketStrategiesCustomizer protobufRSocketStrategyCustomizer() {
return (strategy) -> {
strategy.decoder(new ProtobufDecoder());
strategy.encoder(new ProtobufEncoder());
};
}
Upvotes: 1