Jackson Ray Hamilton
Jackson Ray Hamilton

Reputation: 9466

Java websockets shared session across endpoints

I'm trying to figure out a good way to organize a javax.websocket multiplayer card game I'm working on.

I want to split up my code into multiple classes which are each a ServerEndpoint. My problem is that I need an effective way of sharing session data between them.

I have an index at "/index", which is where I'm currently creating Player objects for clients. I'm setting these like so:

@ServerEndpoint("/index")
public class IndexEndpoint {

  @OnOpen
  public void openConnection(Session session) {
    session.getUserProperties().put("player", new Player());
  }

}

And that works; I can access the Player objects elsewhere throughout IndexEndpoint.

But when I try to access the user properties from another endpoint (after having established a connection with IndexEndpoint in JavaScript, waiting 5 seconds and then opening up an additional connection to LobbyEndpoint on the same page), I get null.

@ServerEndpoint("/lobby")
public class LobbyEndpoint {

  @OnOpen
  public void openConnection(Session session) {
    System.out.println(session.getUserProperties().get("player")); // prints null
  }

}

Which leads me to imply that session data is unfortunately not shared across endpoints.

Is there any good way for me to share websocket session data across multiple classes?

I guess one solution would be to just have one über endpoint for all users to connect to, and which can handle any message type. Then that endpoint delegates message data to other parts of my application.

However I feel like this design would be very messy and restrictive. I'd like to have endpoints dedicated to specific rooms, using annotations like @ServerEndpoint("/rooms/{room-id}") and @PathParam("room-id"). So if I was using a monolithic Endpoint then I couldn't do that; I wouldn't be able to know if a connecting user is a user who access to the room.

Upvotes: 2

Views: 1335

Answers (1)

what about a singleton EJB containing all player and game data?

@Stateless
@ServerEndpoint("/lobby/{sessionKey}")
public class IndexEndpoint {

    @EJB
    GameData data;

    @OnOpen
    public void onOpen(Session session, EndpointConfig config,
            @PathParam("sessionKey") int id) {
        Player player = data.getPlayer(id);
        session.getUserProperties().put("player", player);
    }
}

The first message from the IndexEndpoint could provide the client with its id and then the client could provide its id to the LobbyEndpoint in the ws URL (or in a header with a Configurator), that is how I plan to do it.

Upvotes: 2

Related Questions