The point about running the application on a cluster is more important and relevant than the absence of JSF.
The requirement imposed by the cluster on any solution is that the solution require the use of a shared storage that is accessible to all members of the cluster. There are are several possible solutions that account for this requirement:
- Use a database to store the list of all currently logged in users (with an ID to identify their session; JSESSIONID could be used, but it is better to use an ID that is guaranteed to be unique across all members in the cluster). Even a combination of user ID and cluster member ID will do. This is the easiest, but it will require you to test how your code handles failover (you might have to update the entries in the database on session failover).
- Use the application context (the ServletContext). This is a possible solution, but not recommended at all. Although the application context is bound to be kept up to date in all cluster members, there is a cost to keep the contents up to date (increased network traffic among cluster members).
- Use a distributed caching solution like Terracotta or Coherence. This solution is almost the same as the previous one, except that the session "map" will not be managed in the ServletContext. Network traffic is bound to occur when updating the distributed cache.