The overview of the project is this:
- Upload file to Springboot server via an endpoint
- The endpoint sends an
OKresponse 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().
CodePudding user response:
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
