Current logged users on system
Question
Is there a way to get the current count of logged users?
Answer
There are no out of the box solution. All what we have, is an open session counter which can be used (but this is not only for logged users, that's for all open http session in the environment).
This can be gotten from the org.jahia.bin.listeners.JahiaContextLoaderListener with static method getSessionCount().
But you cannot see how many users are logged.
NOTE: This count is only from one node (if you are in a cluster, other sessions could be created on other nodes).
However, the right solution would be to add an event listener (thanks to the JahiaContextLoaderListener which fire spring events for session activities) which catch CreateSession and DestroySession events.
This solution works for a single server. In this case of cluster, a way must be found to share all the sessions in the whole cluster (or use distributed sessions).
But of a single environment it would be simple module (as you can store the sessions in a local map).
The implementation of a simple example module looks like:
- Create a new simple module
- Add in the module the spring definitions for the two eventlisteners:
<bean id="CreateSessionEventListener" class="org.jahia.modules.loggedusers.listener.CreateSessionEventListener"/> <bean id="DestroySessionEventListener" class="org.jahia.modules.loggedusers.listener.DestroySessionEventListener"/>
- Add the classes for the eventlistners (and a util class where the information are stored in a static hashmap), the listeners are simple. For create session:
public class CreateSessionEventListener implements ApplicationListener<JahiaContextLoaderListener.HttpSessionCreatedEvent> { private static final Logger logger = LoggerFactory.getLogger(CreateSessionEventListener.class); @Override public void onApplicationEvent(HttpSessionCreatedEvent event) { HttpSession session = event.getSession(); LoggedUserUtil.addSession(session); logger.info("session added"); }
- For destroy session:
public class DestroySessionEventListener implements ApplicationListener<JahiaContextLoaderListener.HttpSessionDestroyedEvent> { private static final Logger logger = LoggerFactory.getLogger(CreateSessionEventListener.class); @Override public void onApplicationEvent(HttpSessionDestroyedEvent event) { HttpSession session = event.getSession(); LoggedUserUtil.removeSession(session); logger.info("session removed"); }
and the util class I called it LoggedUserUtil which store the session, and do the check for logged users etc.:
public class LoggedUserUtil { private static final Logger logger = LoggerFactory.getLogger(LoggedUserUtil.class); private static Map<String, HttpSession> sessionMap = new HashMap<String, HttpSession>(); public static long getOpenSessions() { return org.jahia.bin.listeners.JahiaContextLoaderListener.getSessionCount(); } public static void addSession(HttpSession session) { sessionMap.put(session.getId(), session); } public static void removeSession(HttpSession session) { sessionMap.remove(session.getId()); } public static Map<String, HttpSession> getOpenSessionMap() { return sessionMap; } public static long getLoggedUserCount() { long count = 0; for (HttpSession session : sessionMap.values()) { try { if (session.getAttribute("org.jahia.usermanager.jahiauser") != null && !((JahiaUser)session.getAttribute("org.jahia.usermanager.jahiauser")).getUsername().equals(Constants.GUEST_USERNAME)) { count ++; } }catch (IllegalStateException ex) { //session already destroyed remove it from list removeSession(session); } } return count; } }
- For demonstration: Add a very simple content type and a view to display the count of current logged users, the definition looks like:
[jnt:loggedUsers] > jnt:content, jmix:basicContent, jmix:editorialContent
and the view looks like:
<p> Currently are <%=org.jahia.modules.loggedusers.util.LoggedUserUtil.getLoggedUserCount()%> users logged!<br/> </p>
NOTE: When you deploy (or redeploy) the module, the spring beans and java classes are reinitialized (means users which are already logged will not be in the current count). But when you have the module already on startup, the instance everything should be correct!