Java – Spring rest services using SseEmitter

Spring rest services using SseEmitter… here is a solution to the problem.

Spring rest services using SseEmitter

When I call the Controller on the server, I try to notify a simple html page. I have an android app that calls my Controller, and when it’s done I want to notify my web page that the Controller is called.

Here is some of my code:

    @RequestMapping("/user") 
public class UserController {

/**
     * Returns user by id.
     * 
     * @param user IMEI
     * @return
     */
    @RequestMapping(value = "/{imei}", method = RequestMethod.GET)
    public User getUser(@PathVariable String imei) {

User myUser = null;
        try {
            myUser = DbConnector.getUserWithImei(imei);
        } catch (Exception e) {
            System.out.println("Couldn't get user from database");
            e.printStackTrace();
        }
        SseEmitter emitter = new SseEmitter();
        try {
            emitter.send("Hallokes");
        } catch (IOException e) {
             TODO Auto-generated catch block
            e.printStackTrace();
        }
        emitter.complete();
        return myUser;
    }
}

All the tutorials I’ve seen, the Controller returns SseEmitter but I have to return a user. Do I have to make another controller with another map and listen for that URL? How would I call the Controller method in an existing Controller?
What URL does my EventSource have to listen to?

Thank you in advance for your help!

Kind regards.

Solution

I think you’re almost there, Allinone51.

Your call to SseEmitter.send() should probably be in the getUser method.
The general pattern is that when you create a SseEmitter, you need to “store” it somewhere for other code to get it. You correctly returned SseEmitter from the getSseEmitter method, you just forgot to store it so that other methods can call its “send”.

Adjust your example above and it might look like this:

//...
private SseEmitter emitter;

@RequestMapping(value = "/{imei}", method = RequestMethod.GET)
public User getUser(@PathVariable String imei) { 
    User myUser = null;

// .. do resolving of myUser (e.g. database etc).

 Send message to "connected" web page:
    if (emitter != null) {
        emitter.send(myUser.toString());  Or format otherwise, e.g. JSON.
    }

 This return value goes back as a response to your android device
     i.e. the caller of the getUser rest service.
    return myUser;
}

@RequestMapping(value = "/sse")
public SseEmitter getSseEmitter() {
    emitter = new SseEmitter();
    return emitter;
}

Of course, the above code only works for one connection/transmitter. There are smarter ways to store that emitter. For example, in my online gaming application, I hook the emitter into each player object. This way, whenever a player object on my server has something to tell the player device, it can access the correct emitter inside it.

Related Problems and Solutions