How to push notifications from server to client using Spring Boot RSocket (Backend) and Angular (rsocket-js)?

2k views Asked by At

I am planning to use RSocket for my notifications system. I wanted to use Spring Boot RSocket for my backend (Java) while for my frontend, I will be using Angular using rsocket-js.

I was able to quickly spin-up a request-stream interaction model wherein I can pull-in all the notifications within my system. See code snippet for my backend:

  @MessageMapping("streams")
  public Flux<Notification> requestStream() {

    log.info("Streaming to notifications...");

    return streamEventService.retrieveAllNotifications().log();

  }

Now on my frontend, I have the following code snippet:

export class RsocketClientService {

  // backend ws endpoint
  private readonly wsURL = 'ws://localhost:7000/notification';

  client: any;
  socket: any

  constructor() { 
    this.client = new RSocketClient({
      serializers: {
          data: JsonSerializer,
          metadata: IdentitySerializer
      },
      setup: {
          keepAlive: 10000,
          lifetime: 180000,
          dataMimeType: 'application/json',
          metadataMimeType: 'message/x.rsocket.routing.v0',       
          payload: {
            data: 23
          }
      },
      transport: new RSocketWebSocketClient({
          url: this.wsURL
      }),
      responder: new EchoResponder()
    });
  }

  public connect() {
    console.log("initializeSocket...")
    this.client.connect().subscribe({
      onComplete: (socket: any) => {
        this.socket = socket;
        this.socket.connectionStatus().subscribe( (status: any) => {
            console.log("Connection status? ", status);
        });
      },
      onError: (error: any) => {
        console.error("Connection onError? " + error);
      },
      onSubscribe: (cancel: any) => {
        console.log("Connection onSubscribe? cancel?");
      }
    });
  }

 public retrieveNotifications() {
    this.socket.requestStream({
      data: null,
      metadata: String.fromCharCode('streams'.length) + 'streams'
    })
    .subscribe({
      onComplete: () => {
        console.log("onComplete?");
      },
      onError: (error: any) => {
        console.error("onError? error: " + error);
      },
      onNext: (payload: any) => {
        console.log("onNext? payload: ", payload);
      },
      onSubscribe: (subscription: any) => {
        console.log("onSubscribe?");
        subscription.request(1000000);
      },
    });
  }

I have a button in the UI that if clicked will call the method retrieveNotifications which will subscribe to the rsocket message mapping method in my backend requestStream.

Everything is working fine and I could see my responses coming in. Now my question would be, what if on my server there is a new data inserted into the database for example, then how can I send a notification message from my backend server to the frontend saying that "Hey! new data was pushed into the database." I am kind of stuck on how the server will be able to use a somehow fire and forget to the client side.

2

There are 2 answers

0
Elias Khattar On

It looks like you need to create a new controller function that returns a void and when you insert an object in the DB you pass that object to the front end from this function and in angular you connect to it as you did up...try to check this link for fire and forget approach ... hope this helps https://www.baeldung.com/spring-boot-rsocket

0
Bau Nguyen Van On

You want to server-side send request to client-side when connect established.

You can get this connect's RSocketRequester from server then using it create one of four method(FNF, Request-reponse, request-stream, stream-stream) to send request to client. In client-side, you can receive data in EchoResponder class in one of four method above.