Storing session-scope beans in @controller

1.2k Views Asked by At

I am trying to store my session-scoped user beans in a singleton-scoped controller throughout their lifecycle in session. So whenever a user is being connected, I want to store it in an array with the rest of the users those who keep their sessions.

I know about injecting a session-scoped bean into a @Controller through proxy beans so that i have defined my session-scoped user beans as follow,

@Bean
@Scope(value="session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public IUser user ()
{
    IUser user = new MyUser();
    return user;
}

I have used @Autowire annotation to inject that bean into my controller class as below,

@Autowired
private IUser sessionUser;

So whenever a user is getting connected, I am storing that user in a ConcurrentHashMap which is defined and added as below,

    private ConcurrentHashMap<Integer,IUser>    userMap     = new ConcurrentHashMap<>(50,0.9f,2);


    public void addUser(IUser user)
    {
        if(user == null) return;

        IUser retUser =  userMap.putIfAbsent(user.getDbid(),user);
        //...
    }

So everything is working when the first user gets connected, I store its reference to map. Let's assume first user reference is

us.com.soemthing.orm.model.MyUser@135debf

Then let us assume the second user gets connected whose reference is,

us.com.soemthing.orm.model.MyUser@28zbdh

From the references, I can see that my session-scoped beans work fine as their reference is different. However, problems start when execution goes into addUser method. Even before adding the second user to the map, I check my userMap and see that user object it is storing replaced with the second one which is MyUser@28zbdh. So at the end, after adding the second user, My user map looks like this,

Map --> "1"- us.com.soemthing.orm.model.MyUser@28zbdh
Map --> "2"- us.com.soemthing.orm.model.MyUser@28zbdh

So that references are being updated always with the last one. I know that they are the proxy object to real objects but how I can store them?

Thanks

[EDIT] I wanted to provide additional information.

I am calling addUser from another singleton bean as, userInDBMemory.addUser(sessionUser); userInDBMemory is another singleton bean where i add my session user to a ConcurrentHashMap actually. I want to store my current online users on a map as I would like to search and query them without going to the database. So i would like to keep online users (who has a session in context) in memory for easier and faster access. To handle session expires, every online user sends a heartbeat to server to show he is online, I have a scheduled thread on server running in every X minutes and if it finds any user who didn't get heartbeat from the user for a while then it removes it from the map as it means user went offline. To summary my case I have a main controller where i get requests then the chain is like this: @Controller->singleton application bean->Singleton inMemoryDB bean (where I define my map and add user) My SessionUser session-scoped bean is @Autowired in @Controller and i pass it to other singleton beans as a parameter.Thanks for the response.

1

There are 1 best solutions below

0
levye On

I have solved my problem by not storing session-scoped beans directly but their object copies.

//IMyUser sessionUser; --let say sessionUser is session-scoped bean in a singleton bean

so instead of ;

userInDBMemory.addUser(sessionUser);

I have copied the user first and added that object instead.

 IMyUser copyUser = new MyUser();
 BeanUtils.copyProperties(sessionUser, copyUser);
 userInDBMemory.addUser(copyUser);