I'm trying to list currently online users on a pet project I'm working on. I've found a few ways to do it, but I'm having difficutly getting the one I chose to work properly. The basic idea was to use an HttpSessionBindingListener on the users information to add it to a list in the application scope, and remove it when the session was terminated.
My implementation appears to work and the bind/unbind methods look like this:
public class Player implements HttpSessionBindingListener{
//Player variables/methods...
@Override
public void valueBound(HttpSessionBindingEvent event) {
ServletContext context = event.getSession().getServletContext();
ArrayList<Player> logins = (ArrayList<Player>) context.getAttribute("logins");
if(logins==null){
logins=new ArrayList<Player>();
context.setAttribute("logins", logins);
}
logins.add(this);
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
ServletContext context = event.getSession().getServletContext();
ArrayList<Player> logins = (ArrayList<Player>) context.getAttribute("logins");
logins.remove(this);
}
}
But when I tried to write a custom tag to loop through the online players I get null for the "logins" attribute. My tag implementation looks like this:
import java.util.ArrayList;
import java.util.List;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.SimpleTagSupport;
/**
*
*/
public class ListOnlinePlayers extends SimpleTagSupport {
private String var;
/**
* Called by the container to invoke this tag. The implementation of this
* method is provided by the tag library developer, and handles all tag
* processing, body iteration, etc.
*/
@Override
public void doTag() throws JspException {
JspWriter out = getJspContext().getOut();
try {
JspFragment f = getJspBody();
if (f != null) {
List<Player> players = (List<Player>) getJspContext().getAttribute("logins");
if(players==null){
players = new ArrayList<Player>();
getJspContext().setAttribute("logins", players);
}
for(Player p : players){
getJspContext().setAttribute(var, p);
f.invoke(out);
}
getJspContext().removeAttribute(var);
}
} catch (java.io.IOException ex) {
throw new JspException("Error in ListAllPlayers tag", ex);
}
}
public void setVar(String var) {
this.var = var;
}
}
I can only take away from this that SimpleTagSupport.getJspContext()
and/or it's scope are not the same as HttpSessionBindingEvent.getServletContext()
and/or it's scope. While debugging both methods looking through the scopes "logins" is created and the Player is added to it correctly, but I cannot find it while debuggnig the tag and searching through the JspContext.
How can I use a global application scope between custom tags/servlet/jsp? Is there something simple I'm missing about the scope rules? Or is there a different context in one or both I need to use for this?