mcool
mcool

Reputation: 785

How to send data from backend Springboot to client frontend without the use of a Controller?

The overview of the project is this:

  1. Upload file to Springboot server via an endpoint
  2. The endpoint sends an OK response when the file is received, but continues to process the file in the background, running tests on the file.

So, since the endpoint of the controller has already returned a response, how can I send info from the backend to the frontend outside of using the Controller.

Here is what is running after the Controller returns the response:

     CompletableFuture.runAsync(() -> {
            int count = 0;
            boolean stillProcessing = true;
            while (stillProcessing) {
                stillProcessing = !test.isTestComplete();
                if (test.getNumberOfInstancesComplete() > count) {
                    count = test.getNumberOfInstancesComplete();
                    log.info("{}/{} instances completed so far", count, test.getInstances().size());
                }
            }
        });

The log.info line is what I need to return to the frontend React side of things.

The end goal is to basically have a loading bar shown to users using the values printed in log.info().

Upvotes: 1

Views: 2388

Answers (1)

Nikhil Adiga
Nikhil Adiga

Reputation: 150

You can use websockets to notify frontend without a controller. Here is the example code to send a message to the client from backend using STOMP at any time.

@Component
public class PushMessage {

  @Autowired
  SimpMessagingTemplate simpMessagingTemplate;


  public <T> void invokeWebSocketEndpoint(String endpoint, T payload) {
    this.simpMessagingTemplate.convertAndSend(endpoint, payload);
  }

}

For more info on STOMP websockets, check out this link https://spring.io/guides/gs/messaging-stomp-websocket/

If you do not want bi-directional communication between the client and the server and just want to push messages to client from the server you can also make use of Server sent events. Here's a simple example.

  @GetMapping(value = "/test")
  public SseEmitter test() {
    SseEmitter emitter = new SseEmitter();
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    executorService.execute(() -> {
      try {
        Process p = Runtime.getRuntime().exec("ping -c 10 www.google.com");
        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
          String line;
          while ((line = bufferedReader.readLine()) != null) {
            emitter.send(line);
          }
          emitter.complete();
        }
      } catch (IOException e) {
        emitter.completeWithError(e);
        e.printStackTrace();
      }
    });
    executorService.shutdown();
    return emitter;
  }

For more information on Server sent events see this https://www.baeldung.com/spring-server-sent-events

You can consume server sent events from your frontend using the EventSource API https://developer.mozilla.org/en-US/docs/Web/API/EventSource

Upvotes: 1

Related Questions