views:

287

answers:

3

I'm trying to make this 2-player web game application using Spring MVC. I have session-scoped beans Player and application-scoped bean GameList, which creates and stores Game instances and passes them to Players. On player creates a game and gets its ID from GameList and other player sends ID to GameList and gets Game instance. The Game instance has its players as attributes. Problem is that each player sees only himself instead of the other one.

Example of what each player sees:

  1. First player (Alice) creates a game: Creator: Alice, Joiner: Empty
  2. Second player (Bob) joins the game: Creator: Bob, Joiner: Bob
  3. First player refreshes her browser Creator: Alice, Joiner: Alice

What I want them to see is Creator: Alice, Joiner: Bob. Easy way to achieve this is saving information about players instead of references to players, but the game object needs to call methods on its player objects, so this is not a solution.

I think it's because of aop:scoped-proxy of session-scoped Player bean. If I understand this, the Game object has reference to proxy, which refers to Player object of current session. Can Game instance save/access the other Player objects somehow?

beans in dispatcher-servlet.xml:

<bean id="userDao" class="authorization.UserDaoFakeImpl"  />
<bean id="gameList" class="model.GameList" />
<bean name="/init/*" class="controller.InitController" >
     <property name="gameList" ref="gameList" />
     <property name="game" ref="game" />
     <property name="player" ref="player" />
</bean>
<bean id="game" class="model.GameContainer" scope="session">
      <aop:scoped-proxy/>
</bean>
<bean id="player" class="beans.Player" scope="session">
      <aop:scoped-proxy/>
</bean>

methods in controller.InitController

private GameList gameList;
private GameContainer game;
private Player player;
public ModelAndView create(HttpServletRequest request,
        HttpServletResponse response) throws Exception {        
    game.setGame(gameList.create(player));        
    return new ModelAndView("redirect:game");
}
public ModelAndView join(HttpServletRequest request,
        HttpServletResponse response, GameId gameId) throws Exception {
    game.setGame(gameList.join(player, gameId.getId()));       
    return new ModelAndView("redirect:game");
}

called methods in model.gameList

public Game create(Player creator) {        
    Integer code = generateCode();        
    Game game = new Game(creator, code);
    games.put(code, game);
    return game;
}
public Game join(Player joiner, Integer code) {
    Game game = games.get(code);
    if (game!=null) {
        game.setJoiner(joiner);           
    }
    return game;
}
A: 

You can't have the game data in a HTTP session, since that belongs to just one user.

You need to store a reference to the game in both the creator's and the joiner's session.

Espen
+1  A: 

I believe you are right about the proxy being why you see only yourself. Any reference to the proxy will apply to only the object in your session.

Do you need to have the game and player as session scoped? The fact that you are trying to use them across sessions indicates that they are not session scoped data. You could just create them from a factory and store their references in a session scoped bean.

Alternatively, if you do want the player to be session scoped, you could wrap a reference to a prototype in a session bean. You can then use the prototype reference for your cross session data, and the session bean for any session specific local data.

There are several ways to resolve this, but in essence you need to move your cross session data out of the session scoped beans and into an application scope bean which can be shared.

John Smith
+2  A: 

You can't access different session-scoped beans from application-scope.

However, you could do the other way around - register each player in the application-scoped bean, (by calling addPlayer(..))

Bozho