I have some service method which is executing for 3 seconds. I would like to send information to the client when processing starts (HTTPStatus.PROCESSING), and after (3 seconds) when its done(HTTPSTATUS.OK). Now i have this. Can't realize how to improove. It doesn't work correctly
Controller
@RestController
public class MainController {
private ExecutorService nonBlockingService = Executors
.newCachedThreadPool();
@Async
@CrossOrigin
@GetMapping("/sse")
public SseEmitter handleSse() throws IOException, InterruptedException {
SseEmitter emitter = new SseEmitter();
emitter.send(HttpStatus.PROCESSING);
TestService.doSMG();
emitter.send(HttpStatus.OK);
return emitter;
}
}
Service
public class TestService {
public static void doSMG() throws InterruptedException {
TimeUnit.SECONDS.sleep(1);
}
}
Client
<html>
<head>
<script>
var sse = new EventSource('http://localhost:8080/sse');
sse.onmessage = function (evt) {
var el = document.getElementById('sse');
el.appendChild(document.createTextNode(evt.data));
el.appendChild(document.createElement('br'));
};
</script>
</head>
<body>
<p id = "sse">
</p>
</body>
</html>
Your current solution is fully sequential which means it executes everything in order. You should return the SseEmitter as soon as possible and run everything else in a background thread.
To run things in a background thread you want to inject a TaskExecutor or even better an AsyncTaskExecutor so you can submit tasks to it for later execution (as soon there is a thread available for processing).
This would look something like this
@RestController
public class MainController {
private final AsyncTaskExecutor taskExecutor;
public MainController(AsyncTaskExecutor taskExecutor) {
this.tashExecutor=taskExecutor;
}
@CrossOrigin
@GetMapping("/sse")
public SseEmitter handleSse() throws IOException, InterruptedException {
SseEmitter emitter = new SseEmitter();
taskExecutor.submit(() -> {
emitter.send(HttpStatus.PROCESSING);
TestService.doSMG();
emitter.send(HttpStatus.OK);
});
return emitter;
}
}
This will execute the task in the background, while immediatly returning the SseEmitter.