1

As I understand RSocket-JS supports routing messages using encodeCompositeMetadata and encodeRoute, however, I cannot get the server to accept a fireAndForget message. The server constantly logs the following message:

o.s.m.r.a.support.RSocketMessageHandler : No handler for fireAndForget to ''

This is the server mapping I am trying to trigger:

    @Controller
    public class MockController {
        private static final Logger LOGGER = LoggerFactory.getLogger(MockController.class);
    
        @MessageMapping("fire-and-forget")
        public Mono<Void> fireAndForget(MockData mockData) {
            LOGGER.info("fireAndForget: {}", mockData);
            return Mono.empty();
        }
    }

This is the TypeScript code that's trying to make the connection:

    client.connect().subscribe({
        onComplete: socket => {
            console.log("Connected to socket!")
            socket.fireAndForget({
                data: { someData: "Hello world!" },
                metadata: encodeCompositeMetadata([[MESSAGE_RSOCKET_ROUTING, encodeRoute("fire-and-forget")]])
            });
        },
        onError: error => console.error(error),
        onSubscribe: cancel => {/* call cancel() to abort */ }
    });

I've also tried adding the route in other ways (metadata: String.fromCharCode('route'.length)+'route') I found on the internet, but none seem to work.

What do I need to do to format the route in a way that the Spring Boot server recognizes it and can route the message correctly?

Oleh Dokuka
  • 11,613
  • 5
  • 40
  • 65

1 Answers1

1

Binary only communication when using CompositeMetadata

Please make sure that you have configured your ClientTransport with binary codecs as follows:

new RSocketWebSocketClient(
    {
      url: 'ws://<host>:<port>'
    },
    BufferEncoders,
  ),

Having Binary encoders you will be able to properly send your routes using composite metadata.

Also, please make sure that you have configured metadataMimeType as:

...
const metadataMimeType = MESSAGE_RSOCKET_COMPOSITE_METADATA.string; // message/x.rsocket.composite-metadata.v0

new RSocketClient<Buffer, Buffer>({
  setup: {
    ...
    metadataMimeType,
  },
  transport: new RSocketWebSocketClient(
    {
      url: 'ws://<host>:<port>',
    },
    BufferEncoders,
  ),
});

Note, once you enabled BufferEncoders your JSONSeriallizer will not work and you would need to encode your JSON to binary yours selves ( I suggest doing that since in the future versions we will remove support of Serializers concept completely). Therefore, your request has to be adjusted as it is in the following example:

client.connect().subscribe({
        onComplete: socket => {
            console.log("Connected to socket!")
            socket.fireAndForget({
                data: Buffer.from(JSON.stringify({ someData: "Hello world!" })),
                metadata: encodeCompositeMetadata([[MESSAGE_RSOCKET_ROUTING, encodeRoute("fire-and-forget")]])
            });
        },
        onError: error => console.error(error),
        onSubscribe: cancel => {/* call cancel() to abort */ }
    });

Use @Payload annotation for your payload at spring backend

Also, to handle any data from the client and to let Spring know that the specified parameter argument is your incoming request data, you have to annotate it with the @Payload annotation:

@Controller
    public class MockController {
        private static final Logger LOGGER = LoggerFactory.getLogger(MockController.class);
    
        @MessageMapping("fire-and-forget")
        public Mono<Void> fireAndForget(@Payload MockData mockData) {
            LOGGER.info("fireAndForget: {}", mockData);
            return Mono.empty();
        }
    }
Oleh Dokuka
  • 11,613
  • 5
  • 40
  • 65
  • I changed the code to your provided examples and at first it seemed to work. The server stopped outputting errors about not recognizing the route. Now it just doesn't output anything... The server mapping is configured as shown in the Java code. Do you have any idea why it won't trigger `fireAndForget()`? Is it because the server is not recognizing composite metadata? I'm guessing I could probably just use the MESSAGE_RSOCKET_ROUTING mimetype, but what would the code for encoding the route be then? – Ansis Spruģevics May 13 '21 at 10:58
  • fireAndForget does not respond with anything to the client. Try `requestResponse` if you expect to get any values back (am I missing something in your question?) – Oleh Dokuka May 13 '21 at 11:01
  • Also, try this working example of rsocket-js and spring -> https://github.com/OlegDokuka/rsocket-crosslanguage-example – Oleh Dokuka May 13 '21 at 11:01
  • Also, just noticed, your input parameter has no annotation. Please add `@Payload` annotation near your MockData, this can be a cause of your problem – Oleh Dokuka May 13 '21 at 11:05
  • I am not waiting for a response from the server. I am trying to get the server to log the received data to console, but it doesn't. I tried it with the RSocket CLI and that worked so that means there's a problem with the client. – Ansis Spruģevics May 13 '21 at 11:06
  • Also, I tried adding `@Payload` but, as I mentioned, sending a message via the CLI works fine, so that shouldn t be a problem. `@Payload` actually failed to compile, it couldn't find it. I am guessing there is some mimetype confusion between the client and the server. – Ansis Spruģevics May 13 '21 at 11:29
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/232339/discussion-between-ansis-spruevics-and-oleh-dokuka). – Ansis Spruģevics May 13 '21 at 11:29