JSP scope=application causes class cast exception

I have a JSP that uses a bean called UserCredentials with session scope and a bean called SessionManager with application scope.

The problem is that my JSP causes a class cast exception unless I change the scope of the SessionManager to _session_ as well - then I don't get any errors, but this causes to many connections to be created, and SessionManager cannot do its job properly because all of the other sessions are out of scope.

Please help, thnx

(server using apache/tomcat)

[514 byte] By [rayb_chillin] at [2007-9-26 3:43:47]
# 1
Can you post your code ?
neville_sequeira at 2007-6-29 12:22:53 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 2

Thanks for the reply - posting code that should work(sorry for the amount....)

SessionManager & UserCredentials

from InstantJavaServerPages

** extra bucks available **

//SessionManager - scope=application

package com.srcdesign;

import java.sql.Connection;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Enumeration;

import java.util.Hashtable;

import java.util.Vector;

import javax.servlet.ServletContext;

public class SessionManager

{private Hashtable currentLogins;

private ConnectionPool connectionPool;

private boolean initialized = false;

private static final int TIMEOUT_MINUTES = 5;

private static final long ONE_MINUTE = 60000L;

private static final String POOL_CFG_FILE = "ConnectionPool.cfg";

private static final String SELECT_PASSWORD = "SELECT password FROM idpassword WHERE userid = ";

private static final String SELECT_ACCOUNT_STATUS = "SELECT COUNT(*) FROM idpassword WHERE status = false AND userid = ";

private static final String UPDATE_ACCOUNT_STATUS = "UPDATE idpassword SET status = false WHERE userid = ";

private static final String SELECT_SESSION_STATS = "SELECT COUNT(*) FROM sessionstats WHERE sessionid = ";

private static final String UPDATE_SESSION_STATS = "UPDATE sessionstats SET endtime = ";

private static final String INSERT_RAW_STATS = "INSERT INTO rawpagestats" + "(userid, sessionid, dt, tm, pagedesc) VALUES (";

private static final String HITS_PLUS_QUALIFIER = "hits = hits + 1 WHERE sessionid = ";

private static final String RPAREN = ")";

private static final String COMMA = ",";

private static final String QUOTE = "'";

private class LoginProfile extends UserCredentials

{boolean isLoggingIn;

int loginAttempts;

boolean isLoggedIn;

Date loginTime;

Date lastActivity;

boolean isAlive;

int minutesToTimeout;

public LoginProfile(UserCredentials credentials)

{setUser(credentials.getUser());

setPassword(credentials.getPassword());

isLoggingIn = true;

isLoggedIn = false;

loginAttempts = 0;

isAlive = false;

minutesToTimeout = TIMEOUT_MINUTES;

}

}

class InactivityMonitor implements Runnable

{public void run()

{while (true)

{try

{Thread.sleep(ONE_MINUTE);

synchronized (currentLogins)

{Enumeration keyEnumerator = currentLogins.keys();

Vector expiredKeys = new Vector();

while (keyEnumerator.hasMoreElements())

{String key = (String)keyEnumerator.nextElement();

processElement(expiredKeys, key);

}

Enumeration expiredEnumerator = expiredKeys.elements();

while (expiredEnumerator.hasMoreElements())

{currentLogins.remove(expiredEnumerator.nextElement());

}

}

}

catch (InterruptedException e)

{

}

} // end while

}

private void processElement(Vector expiredKeyTable, String key)

{LoginProfile profile = (LoginProfile)currentLogins.get(key);

if (!profile.isLoggingIn)

{//if (!profile.isAlive) {

if (profile.minutesToTimeout <= 0)

{// mark this one for removal

expiredKeyTable.add(key);

}

else

{// prepare for removal in 5 minutes time...

//profile.isAlive = false;

--profile.minutesToTimeout;

currentLogins.put(key,profile);

}

}

}

}

public SessionManager()

{

}

public void initialize() throws Exception

{if (initialized)

{return;

}

connectionPool = new ConnectionPool();

connectionPool.initialize(POOL_CFG_FILE);

currentLogins = new Hashtable();

InactivityMonitor monitor = new InactivityMonitor();

Thread monitorThread = new Thread(monitor);

monitorThread.start();

initialized = true;

}

public boolean isLoggingIn(UserCredentials credentials)

{boolean loggingIn = false;

String user = credentials.getUser();

synchronized (currentLogins)

{if (currentLogins.containsKey(user))

{LoginProfile aProfile = (LoginProfile)currentLogins.get(user);

loggingIn = aProfile.isLoggingIn;

}

}

return loggingIn;

}

public boolean alreadyLoggedIn(UserCredentials credentials)

{boolean loggedIn = false;

String user = credentials.getUser();

synchronized (currentLogins)

{if (currentLogins.containsKey(user))

{LoginProfile aProfile = (LoginProfile)currentLogins.get(user);

loggedIn = aProfile.isLoggedIn;

}

}

return loggedIn;

}

public int getLoginAttempts(UserCredentials credentials)

{int loginAttempts = 0;

String user = credentials.getUser();

synchronized (currentLogins)

{if (currentLogins.containsKey(user))

{LoginProfile aProfile = (LoginProfile)currentLogins.get(user);

loginAttempts = aProfile.loginAttempts;

}

}

return loginAttempts;

}

public void incrementLoginAttempts(UserCredentials credentials)

{String user = credentials.getUser();

synchronized (currentLogins)

{if (currentLogins.containsKey(user))

{LoginProfile aProfile = (LoginProfile)currentLogins.get(user);

++aProfile.loginAttempts;

currentLogins.put(user, aProfile);

}

}

}

public boolean keepAlive(UserCredentials credentials, String pageInfo) throws SQLException

{if (!alreadyLoggedIn(credentials))

{return false;

}

updateSessionStats(credentials);

String user = credentials.getUser();

synchronized (currentLogins)

{if (currentLogins.containsKey(user))

{LoginProfile aProfile = (LoginProfile)currentLogins.get(user);

aProfile.isAlive = true;

aProfile.minutesToTimeout = TIMEOUT_MINUTES;

currentLogins.put(user, aProfile);

}

}

logRawStats(credentials, pageInfo);

return true;

}

private int getCount(ResultSet rs) throws SQLException

{rs.next();

return rs.getInt(1);

}

public boolean isSuspended(UserCredentials credentials) throws SQLException

{String user = credentials.getUser();

Connection conn = connectionPool.getConnection();

Statement qs = conn.createStatement();

ResultSet rs = qs.executeQuery(SELECT_ACCOUNT_STATUS + QUOTE + user + QUOTE);

boolean tf = (getCount(rs) > 0);

connectionPool.close(conn);

return tf;

}

public void suspendAccount(UserCredentials credentials) throws SQLException

{String user = credentials.getUser();

synchronized (currentLogins)

{currentLogins.remove(user);

}

Connection conn = connectionPool.getConnection();

Statement us = conn.createStatement();

us.executeUpdate(UPDATE_ACCOUNT_STATUS + QUOTE + user + QUOTE);

connectionPool.close(conn);

}

public boolean login(UserCredentials credentials) throws SQLException

{if (alreadyLoggedIn(credentials))

{return false;

}

String user = credentials.getUser();

LoginProfile profile;

synchronized (currentLogins)

{if (currentLogins.containsKey(user))

{profile = (LoginProfile)currentLogins.get(user);

}

else

{profile = new LoginProfile(credentials);

}

}

Connection conn = connectionPool.getConnection();

Statement qs = conn.createStatement();

ResultSet rs = qs.executeQuery(SELECT_PASSWORD + QUOTE + user + QUOTE);

while (rs.next())

{if (rs.getString(1).equals(credentials.getPassword()))

{profile.isLoggingIn = false;

profile.isLoggedIn = true;

break;

}

}

synchronized (currentLogins)

{currentLogins.put(user, profile);

}

return profile.isLoggedIn;

}

public void initiateSessionLogging(UserCredentials credentials) throws SQLException

{String user = credentials.getUser();

String sessionId = credentials.getSessionId();

Connection conn = connectionPool.getConnection();

Statement qs = conn.createStatement();

ResultSet rs = qs.executeQuery(SELECT_SESSION_STATS + QUOTE + sessionId + QUOTE + " AND userid = " + QUOTE + user + QUOTE);

if (getCount(rs) == 0)

{java.util.Date dt = new java.util.Date();

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

String ft = sdf.format(dt);

Statement us = conn.createStatement();

us.executeUpdate("insert into sessionstats " + "(sessionid, userid, starttime, endtime, hits) VALUES (" + QUOTE + sessionId + QUOTE + COMMA + QUOTE +user + QUOTE + COMMA + QUOTE + ft + QUOTE + COMMA + QUOTE + ft + QUOTE + COMMA + "0" + RPAREN);

}

connectionPool.close(conn);

}

public void logRawStats(UserCredentials credentials, String pageInfo) throws SQLException

{String user = credentials.getUser();

String sessionId = credentials.getSessionId();

java.util.Date dt = new java.util.Date();

SimpleDateFormat sdfd = new SimpleDateFormat("yyyy-MM-dd");

String fd = sdfd.format(dt);

SimpleDateFormat sdft = new SimpleDateFormat("HH:mm:ss");

String ft = sdft.format(dt);

Connection conn = connectionPool.getConnection();

Statement us = conn.createStatement();

us.executeUpdate(INSERT_RAW_STATS + QUOTE +user + QUOTE + COMMA + QUOTE + sessionId + QUOTE + COMMA + QUOTE + fd + QUOTE + COMMA + QUOTE + ft + QUOTE + COMMA + QUOTE + pageInfo.replace('\'','`') + QUOTE + RPAREN);

connectionPool.close(conn);

}

public void updateSessionStats(UserCredentials credentials) throws SQLException

{String user = credentials.getUser();

String sessionId = credentials.getSessionId();

Connection conn = connectionPool.getConnection();

Statement qs = conn.createStatement();

ResultSet rs = qs.executeQuery(SELECT_SESSION_STATS + QUOTE + sessionId + QUOTE + " and userid = " + QUOTE + user + QUOTE);

if (getCount(rs) > 0)

{java.util.Date dt = new java.util.Date();

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

String ft = sdf.format(dt);

Statement us = conn.createStatement();

us.executeUpdate(UPDATE_SESSION_STATS + QUOTE + ft + QUOTE + COMMA + HITS_PLUS_QUALIFIER + QUOTE + sessionId + QUOTE);

}

connectionPool.close(conn);

}

public void logout(UserCredentials credentials)

{synchronized (currentLogins)

{currentLogins.remove(credentials.getUser());

}

}

}

//=====================================

// UserCredentials - scope=session

package com.srcdesign;

public class UserCredentials

{private String user;

private String password;

private String sessionId;

public UserCredentials()

{user = "";

password = "";

sessionId = "";

}

public String getUser()

{return user;

}

public void setUser(String user)

{this.user = user;

}

public String getPassword()

{return password;

}

public void setPassword(String password)

{this.password = password;

}

public String getSessionId()

{return sessionId;

}

public void setSessionId(String sessionId)

{this.sessionId = sessionId;

}

}

rayb_chillin at 2007-6-29 12:22:53 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 3
Ok. Time to bite some more. Can you post the stack trace of the exception you get ?
neville_sequeira at 2007-6-29 12:22:53 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 4

** Here it is...thanks in advance. **

Internal Servlet Error:

javax.servlet.ServletException: com.srcdesign.SessionManager

at org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:459)

at _0002flogin_0002ejsplogin_jsp_50._jspService(_0002flogin_0002ejsplogin_jsp_50.java:138)

at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:119)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)

at org.apache.jasper.servlet.JspServlet$JspServletWrapper.service(JspServlet.java:177)

at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:318)

at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:391)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)

at org.apache.tomcat.core.ServletWrapper.doService(ServletWrapper.java:404)

at org.apache.tomcat.core.Handler.service(Handler.java:286)

at org.apache.tomcat.core.ServletWrapper.service(ServletWrapper.java:372)

at org.apache.tomcat.core.ContextManager.internalService(ContextManager.java:797)

at org.apache.tomcat.core.ContextManager.service(ContextManager.java:743)

at org.apache.tomcat.service.http.HttpConnectionHandler.processConnection(HttpConnectionHandler.java:210)

at org.apache.tomcat.service.TcpWorkerThread.runIt(PoolTcpEndpoint.java:416)

at org.apache.tomcat.util.ThreadPool$ControlRunnable.run(ThreadPool.java:498)

at java.lang.Thread.run(Thread.java:484)

//===================================

Root cause:

java.lang.ClassCastException: com.srcdesign.SessionManager

at _0002flogin_0002ejsplogin_jsp_50._jspService(_0002flogin_0002ejsplogin_jsp_50.java:63)

at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:119)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)

at org.apache.jasper.servlet.JspServlet$JspServletWrapper.service(JspServlet.java:177)

at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:318)

at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:391)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)

at org.apache.tomcat.core.ServletWrapper.doService(ServletWrapper.java:404)

at org.apache.tomcat.core.Handler.service(Handler.java:286)

at org.apache.tomcat.core.ServletWrapper.service(ServletWrapper.java:372)

at org.apache.tomcat.core.ContextManager.internalService(ContextManager.java:797)

at org.apache.tomcat.core.ContextManager.service(ContextManager.java:743)

at org.apache.tomcat.service.http.HttpConnectionHandler.processConnection(HttpConnectionHandler.java:210)

at org.apache.tomcat.service.TcpWorkerThread.runIt(PoolTcpEndpoint.java:416)

at org.apache.tomcat.util.ThreadPool$ControlRunnable.run(ThreadPool.java:498)

at java.lang.Thread.run(Thread.java:484)

rayb_chillin at 2007-6-29 12:22:53 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 5
The problem is most likely in the way you use the classes in your JSP page. Can you post a simple JSP page that demonstrates how you're using the classes? -either the relevant bits of your page or (even better) a simple example that causes the same error you're getting?
mattbunch at 2007-6-29 12:22:53 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 6

Sample JSP....

//================

<jsp:useBean id="sessionManager" class="com.srcdesign.SessionManager" scope="application" />

<jsp:useBean id="credentials" class="com.srcdesign.UserCredentials" scope="session" />

<%

sessionManager.initialize();

if (sessionManager.alreadyLoggedIn(credentials))

{

%>

<jsp:forward page="logout.jsp" />

<%

}

%>

rayb_chillin at 2007-6-29 12:22:53 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 7
The exception you posted earlier hints at some problem in login.jsp. I think you better post code for login.jsp
neville_sequeira at 2007-6-29 12:22:53 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 8

As requested...complete listing of login.jsp...thanks again for taking a look...

<jsp:useBean id="sessionManager" class="com.srcdesign.SessionManager" scope="application" />

<jsp:useBean id="credentials" class="com.srcdesign.UserCredentials" scope="session" />

<%

sessionManager.initialize();

if (sessionManager.alreadyLoggedIn(credentials))

{

%>

<jsp:forward page="logout.jsp" />

<%

}

%>

<HTML>

<HEAD>

<TITLE>myserver.com</TITLE>

<SCRIPT LANGUAGE="JavaScript">

function giveFocus()

{document.login.user.focus();

}

function submitForm()

{document.login.submit();

}

function resetForm()

{document.login.reset();

document.login.user.focus();

}

</SCRIPT>

<SCRIPT LANGUAGE="javascript">

<!--

if (screen.width>=1024||screen.height>=768)

{document.write("<LINK REL=\"stylesheet\" HREF=\"lawyer.css\" TYPE=\"text/css\">");

}

else

{document.write("<LINK REL=\"stylesheet\" HREF=\"lawyer_low.css\" TYPE=\"text/css\">");

}

//-->

</SCRIPT>

</HEAD>

<BODY BGCOLOR="#ffffff" ONLOAD="giveFocus();">

<CENTER>


<TABLE WIDTH="70%" HEIGHT=30 CELLPADDING=0 CELLSPACING=0 BORDER=0>

<TR>

<TD BGCOLOR="#000000" VALIGN="TOP"><IMG SRC="tl_000000_ffffff.gif" BORDER=0></TD>

<TD BGCOLOR="#000000" ALIGN="CENTER" WIDTH="100%"><FONT COLOR="#ffffff" SIZE=2><CENTER><B>Corporate Section - Authorized Use Only</B></CENTER></FONT></TD>

<TD BGCOLOR="#000000" VALIGN="TOP"><IMG SRC="tr_000000_ffffff.gif" BORDER=0></TD>

</TR>

<TR>

<TD COLSPAN=3 BGCOLOR="#ff0000"></TD>

</TR>

</TABLE>



<B>Login:</B>




<FORM NAME="login" METHOD=POST ACTION="http://www.myserver.com:8081/myserver-wa/validate.jsp">

<TABLE WIDTH="50%">

<TR>

<TD ALIGN="RIGHT"><P><B>UserName</B></P></TD>

<TD><INPUT NAME="user" TYPE="TEXT" LENGTH=9 MAXLENGTH=9></TD>

</TR>

<TR>

<TD ALIGN="RIGHT"><P><B>Password</B></P></TD>

<TD><INPUT NAME="password" TYPE="PASSWORD" LENGTH=8 MAXLENGTH=8></TD>

</TR>

</TABLE>



<INPUT TYPE="BUTTON" VALUE="Login" ONCLICK="submitForm();">

<INPUT TYPE="BUTTON" VALUE="Reset" ONCLICK="resetForm();">

</FORM>

</CENTER>

</BODY>

</HTML>

rayb_chillin at 2007-6-29 12:22:53 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 9

In your login.jsp, it seems the only code from which a java.lang.ClassCastException can be thrown is the <jsp:useBean> tag.

As per the JSP specifications, this tag causes a java.lang.ClassCastException exception to be raised if an object with the specifid name("sessionManager" in your case) was found in the specified scope("application" in your case) but that object could not be cast to the desired class type("com.srcdesign.SessionManager" in your case).

Where are putting an object to application scope(i.e. ServletContext in servlet terms) ?

Maybe you have some code somewhere else, such as servlet etc, from where you are putting an object named "sessionManager" to servlet context, but that object is not of type com.srcdesign.SessionManager.

neville_sequeira at 2007-6-29 12:22:53 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 10

I am (obviously) new to server side java, so your last post leads me to this question.

Is it possible, that an earlier version of SessionManager is still running in the application scope, and that is causing the class cast exception because the classes are no longer the same? There were some open connections to the DB from the earlier flawed version - along with your post, I was lead to this conclusion.

I renamed the class Manager, made the appropriate changes in the jsp files, and everything seems to work now.

Reply and let me know what you think.

Thanks again.

rayb_chillin at 2007-6-29 12:22:53 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 11

If you accessed the JSP atleast once previously, and then changed and compiled the class SessionManager. But did not change the JSP. And then accessed the JSP again, then it is possible to get class cast exceptions.

To avoid such issues I always clean up(i.e delete) the servlet class files automatically produced by the JSP compiler for my JSP and restart Tomcat.

Such a problen can also occur with servlets. I do the same(i.e. restart Tomcat) for that also.

If this seems confusing, don't worry, you are not the first one. However, I think you better read the document %TOMCAT_HOME%\doc\uguide\tomcat_ug.html Specifically whatever is said against reloadable under server.xml under Tomcat's Configuration Files

neville_sequeira at 2007-6-29 12:22:53 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 12
thanks again...all is well in the world again...duke dollars delivered :)
rayb_chillin at 2007-6-29 12:22:53 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...