tom
tom

Reputation: 2357

SSE from Java to Web Browser

I thought that emitting HTTP SSE from Java and handling those connections shouldn't be that complicated, but I can't figure it out how to do that.

I have one server (Java SE 11) and multiple clients (Web Browsers with JavaScript) that start listening for messages from the server. (I'm testing on localhost)

The client-side is very simple:

var evtSource = new EventSource("localhost/javaapp");

evtSource.onmessage = function(e) {
  console.log("message: " + e.data);
}

evtSource.onerror = function(e) {
  console.log("sse failed");
}

But for the server-side I have no idea. After some investigation I've found that I should maybe use the javax.ws.rs.sse API, but all it has are interfaces and the example code snippets you find are using a lot of @Annotations, things I'd like to avoid.

Do I even need this API? Or could I maybe just create a basic HTTP connection with the proper headers? But then how to implement all the features SSE has? The automatic keep alive and so on...

The aim is to handle all the clients separately. They subscribe to the server, and in case some event occurs for one, the server sends a message to that one. So it's not about broadcasting the same thing to all.

Upvotes: 2

Views: 580

Answers (1)

Falah H. Abbas
Falah H. Abbas

Reputation: 512

Using Spring Web you can simply create a SseEmitter object then send data to it.

and you can receive data from your client as it is.


@Controller
@RequestMapping(path = "api/person")
public class PersonController {

    @Autowired
    private PersonRepository personRepository;
    private Optional<SseEmitter> sseEmitter = Optional.empty();

    @PostMapping(path = "/add")
    public @ResponseBody
    String addPerson(@RequestBody Person person) {
        personRepository.save(person);
        sseEmitter.ifPresent(sseEmitter1 -> {
                    try {
                        sseEmitter1.send(person);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
        );
        return "Saved";
    }

    @GetMapping(path = "/onPersonAdded")
    public SseEmitter onPersonAdded() {
        sseEmitter = Optional.of(sseEmitter.orElse(new SseEmitter(-1L)));
        return sseEmitter.get();
    }
}

Upvotes: 4

Related Questions