2

I am facing a similar problem and have learnt that my listener class will be instantiated when the web.xml is read. I have few functions in the listener class that are used by the main servlet's doPost(which interacts with the database(mysql) to read/write data regarding the users.)along with the methods of HttpSessionListener. So what prevents the container from loading the listener class. I am getting the 404 error.

snippet:

public class EntryServlet extends HttpServlet{
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {


    PlayersList playa = new PlayersList(); //listener class

    if(!playa.isExisting(params[3])){
        if(params[1].equals("Register")){           
            playa.addPlayer(params);
        }
    }       
    else
        out.println("Username already exists");


    if(playa.isExisting(params[argUName],params[argUPwd])){
        HttpSession session = request.getSession(true);     
        session.setMaxInactiveInterval(600);            
        HashMap playersMap = playa.getActivePlayers();
        //code . .
    }
    else
        out.println("Couldn't locate player Name!");    
        out.println(playa.getIn());         
}

Listener class:

public class PlayersList implements HttpSessionListener{
private Connection cn;
private Statement st;

PlayersList(){
    try{
        Class.forName("com.mysql.jdbc.Driver");
        cn =  DriverManager.getConnection("jdbc:mysql://localhost/homeDbse\'","root","");
        st = cn.createStatement();
    }
    catch(ClassNotFoundException ce){}
    catch(SQLException se){}
    catch(Exception e){}
}   

public boolean isExisting(String player){
    //interaction with dbse
}   

public void addPlayer(String[] args){
    //interaction with dbse

}   
public void sessionCreated(HttpSessionEvent se){
    //session managing
}   
public void sessionDestroyed(HttpSessionEvent se){
    //session managing
}
Community
  • 1
  • 1
sarath
  • 498
  • 2
  • 12
  • 19
  • Your have some empty catch blocks in the constructor of PlayersList. Put some e.printStackTrace() to see what's happening. It's not the container instantiating the listener in this case, it's you, because you call PlayersList playa = new PlayersList(); //listener class – Victor Ionescu Mar 10 '11 at 12:59
  • I emptied them to make the code short :P and where will the System.out print the result? I didnt know how to check for the error messages. can you explain this part: It's not the container instantiating the listener in this case, it's you, because you call PlayersList playa = new PlayersList(); The other question that I linked says the listener is instantiated by the container when web.xml is read. – sarath Mar 10 '11 at 13:04
  • System.out and System.err print the result to the console. Yes, the listener is instantiated by the container and is called by the container when the session is destroyed. But the one you declare in your code is instantiated by you as a regular class, and has nothing to do with the container. – Victor Ionescu Mar 10 '11 at 13:15
  • So what will be the solution? – sarath Mar 10 '11 at 13:19
  • I don't know. You'll have to debug a little bit I guess. You get a 404, but you don't know what caused it yet. It's for you to find out, dig deeper. – Victor Ionescu Mar 10 '11 at 13:21

1 Answers1

7

This approach is completely wrong. You should be doing it from the other side on. Create a Player object which implements HttpSessionBindingListener and use it instead.

public class Player implements HttpSessionBindingListener {

    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        // Add player to list.
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        // Remove player from list.
    }

    // ...

}

The valueBound() will be triggered when you do

Player player = new Player(name);
request.getSession().setAttribute("player", player);

The valueUnbound() will be triggered when the session has expired or when you remove the attribute.


Unrelated to the concrete problem, you have serious JDBC problems in your code. This application will crash whenever the DB times out the connection because it's been open for too long. You should open and close the connection, statement and resultset in the shortest possible scope. I.e., close them in the finally block of the very same try block where the SQL query is been executed.

Montia
  • 35
  • 1
  • 8
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • May I know whats wrong with the working? apart from the poor approach! – sarath Mar 10 '11 at 16:12
  • Because you're constructing a `HttpSessionListener` instance inside `doPost()`. It's intented to be registered in `web.xml` and created by the servletcontainer itself. There needs to be only one instance of it during whole webapp's lifetime which intercepts on all user sessions. – BalusC Mar 10 '11 at 16:15
  • How should I be maintaining the Database connection? One per player object? – sarath Mar 10 '11 at 16:48
  • No. One per SQL transaction. Use a connection pool if you want to reuse connections. You should **definitely** not declare the `Connection` or other SQL resources outside the method block where the SQL query/queries are been executed. – BalusC Mar 10 '11 at 16:50
  • Hi, I am facing a problem now. `request.getSession().setAttribute("player", player);` when i refresh the page this line is executed again causing the previous player to be unbound. How to fix it? – sarath Mar 10 '11 at 18:28
  • Just check if the player isn't already present in session. I.e. `if (request.getSession().getAttribute("player") == null) { create player }`. – BalusC Mar 10 '11 at 18:31
  • wait! think I got it wrong. so the setAttribute should have a unique name each time I create a player? (1st argument). I used "player"(with quotes). SO there is the problem? – sarath Mar 10 '11 at 18:34
  • Why would you create muliple players per user session? One user is one player, right? – BalusC Mar 10 '11 at 18:35
  • ya but what happens when a 2nd user logs in. Wont he get registered under same name? (setAttribute(`"player"`, player); – sarath Mar 10 '11 at 18:38
  • It just uses a different session. Multiple webpage visitors don't share the same session (only when you open multiple browser tabs/windows on the same session, the same session will be used). And no, this is a different problem. – BalusC Mar 10 '11 at 18:42
  • I dont understand. say I am logging in. setAttribute("player", player) is excuted. And another person logs in and setAttribute("player", player) is executed. now what will getAttribute("player") return? – sarath Mar 10 '11 at 18:45
  • It will just return the one for the user itself. Sessions are not shared among webpage visitors. You can test it yourself by spawning different webbrowsers (e.g. one Firefox and one Chrome) or using different machines. Go learn about sessions: http://stackoverflow.com/questions/3106452/java-servlet-instantiation-and-session-variables/3106909#3106909 – BalusC Mar 10 '11 at 18:45
  • Oh! so then why is valueUnbound called when I refresh the page? – sarath Mar 10 '11 at 18:46
  • Because you're not checking if the user is already in the session. You're overridding it blindly with a brand new one. See earlier comment. – BalusC Mar 10 '11 at 18:47