Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / November 2005

Tip: Looking for answers? Try searching our database.

servlet problems with session attributes

Thread view: 
Pep - 23 Nov 2005 13:23 GMT
I have a servlet application running in Tomcat that uses jsp forms and java
classes. I use session attributes to to preserve data across the session
and to comunicate across servlet objects.

One of the server attributes that I set is a ArrayList containing the
results of a mysql select statement.

No matter what I do I cannot clear the ArrayList contents without restarting
the Tomcat container!

I have removed the session attribute that contains the ArrayList in the form
that processes the container. I dump the session attribute names when I
re-enter the search form and there is no session attribute for the
ArrayList, yet when I execute a search operation I end up with the previous
ArrayList with the new search results appended to the end!

I even invalidate the session when I execute a logout in the my application
which does clear everything but when I log back in and do a search the same
thing happens and I end up with the new search results tacked to the end fo
the previous ArrayList!

Worse, if I login to a separate concurrent session using a different browser
and do a search, the same thing happens and I end up with the results
appended to the end of the list that was created in another users session!

The only way I can clear this ArrayList is to restart the Tomcat container!

Help,
Pep.
Robert Klemme - 23 Nov 2005 13:35 GMT
> I have a servlet application running in Tomcat that uses jsp forms
> and java classes. I use session attributes to to preserve data across
[quoted text clipped - 28 lines]
> Help,
> Pep.

Probably the problem is not in your web app but in the code that reads
results from the DB.  Maybe someone declared a static or non static member
and returns a reference to the same instance every time data is read from
the db.

Kind regards

   robert
Pep - 23 Nov 2005 13:51 GMT
>> I have a servlet application running in Tomcat that uses jsp forms
>> and java classes. I use session attributes to to preserve data across
[quoted text clipped - 37 lines]
>
>     robert

I have gone back over the code to check for static variables as I have
fallen foul of that in the past and have not found any.  However a further
scan would not be to costly and I concentrated on the ArrayList declaration
so it is possible there is something lower in the code where I actually
read the database.

That someone would be me if it has been done as I am the only coder on this
project :)

Cheers,
Pep.
Robert Klemme - 23 Nov 2005 14:18 GMT
>>> I have a servlet application running in Tomcat that uses jsp forms
>>> and java classes. I use session attributes to to preserve data
[quoted text clipped - 46 lines]
> That someone would be me if it has been done as I am the only coder
> on this project :)

LOL An easy check would be to wrap your method that returns the array list
with another method that copies list contents to a newly created list and
clears the original...

   robert
Pep - 23 Nov 2005 14:35 GMT
>>>> I have a servlet application running in Tomcat that uses jsp forms
>>>> and java classes. I use session attributes to to preserve data
[quoted text clipped - 52 lines]
>
>     robert

I have just posted the code in response to Andrea's post and as you can see
I start out with a new ArrayList each time the servlet is enterred and I
clear the session attribute before it is enterred but this does not solve
the problem.

It's behaving as though the ArrayList is of container scope?

I checked to see how many rows were being retrieved in the sql statement
each time the servlet is executed and sure enough it is only the number I
expect and also the size of the ArrayList before being set as the session
attribute is as expected?

Cheers,
Pep.
Robert Klemme - 23 Nov 2005 14:47 GMT
>>>>> I have a servlet application running in Tomcat that uses jsp forms
>>>>> and java classes. I use session attributes to to preserve data
[quoted text clipped - 56 lines]
> can see I start out with a new ArrayList each time the servlet is
> enterred

Definitely not!  You have a new ArrayList every time the servlet is
instantiated.  That's something different and it usually happens only once
during tomcat's life cycle.  Make it a local variable (i.e. in doPost()).

You probably need to dig a bit deeper into Servlet documentation
(tutorial)...

Kind regards

   robert
Pep - 23 Nov 2005 15:05 GMT
<snip>

>> I have just posted the code in response to Andrea's post and as you
>> can see I start out with a new ArrayList each time the servlet is
[quoted text clipped - 10 lines]
>
>     robert

Thanks very much for being kind there :)

I have solved the problem with that little pointer form you and have
addressed further examples of this problem in my code suite because of it.

It's a pity as it means that I need to use local variables and pass them as
function parameters within the same class instead of using class variables.

Ho hum, so in effect class variables are actually container variables?

I will definitely go back to reading the manuals regarding this area :)

Cheers,
Pep.
Viator - 23 Nov 2005 15:22 GMT
A global variable like your 'agentArray' is associated with the
instance of the servlet not the request. You said in your previous
message that it is instantiated every time the servlet is entered but
the fact is that the servlet is entered in doXXXX methods rather than
in constructor because server does not (or might not) create one
servlet instance per request. Actually many requests are served by same
instance of servlet and this is how J2EE works. One more thing is that
the class variables in servlets are not container variables by any
means but they are class variables only. The only thing you need to
understand is that one request for the servlet is not necessarily going
to create an instance of the servlet. This is true of course if you are
not implementing SingleThreadModel interface.

Amit :-)
Pep - 23 Nov 2005 15:31 GMT
> A global variable like your 'agentArray' is associated with the
> instance of the servlet not the request. You said in your previous
[quoted text clipped - 10 lines]
>
> Amit :-)

Yep got it, that was my clumsy way of saying that I now understand that
class variables are not instantiated once per call to the servlet :)
Robert Klemme - 23 Nov 2005 15:34 GMT
> A global variable like your 'agentArray' is associated with the
> instance of the servlet not the request.

It's not directly a global variable in the sense of the Java language.
It's simply an instance variable (or member).

> You said in your previous
> message that it is instantiated every time the servlet is entered but
> the fact is that the servlet is entered in doXXXX methods rather than
> in constructor because server does not (or might not) create one
> servlet instance per request.

I guess, the container is actually allowed to create a servlet instance
per request - although that would be inefficient.

> Actually many requests are served by
> same instance of servlet and this is how J2EE works.

Right.

> One more thing
> is that the class variables in servlets are not container variables
> by any means but they are class variables only.

It's not a class variable, it's an instance variable!

> The only thing you
> need to understand is that one request for the servlet is not
> necessarily going to create an instance of the servlet. This is true
> of course if you are not implementing SingleThreadModel interface.

Even then.  The container is only required to ensure that no more than one
thread at a time enters one of the doX methods of a single thread model
servlet.  Subsequent requests may be routed through the same servlet
nevertheless.

Use instance variables in servlets only for things that should have the
same life cycle as the servlet instance.  Everything else must be done
with local variables.  IMHO servlets should not be complex anyway so if
you need more complex calculations you can for example resort to command
pattern, i.e., delegate the real work to another class's instance that is
created per request.

Folks, know your tools!  The servlet spec isn't really unreadable.  Just
spend the time to read and understand.  Will save you a lot of hassle...

Kind regards

   robert
Pep - 23 Nov 2005 15:45 GMT
<snip>

> Folks, know your tools!  The servlet spec isn't really unreadable.  Just
> spend the time to read and understand.  Will save you a lot of hassle...
>
> Kind regards
>
>     robert

Well I will certainly be doing more reading on this littel puppy now that I
fell foul of that :)
Viator - 23 Nov 2005 15:45 GMT
Thanks for correcting me on SingleThreadModel.
Regarding class variables; they are class variable only while instance
variables are instance variable.
I admit that I should have written instance variable there.
Thanks again.
Amit :-)
Jimi Hullegård - 24 Nov 2005 00:58 GMT
> <snip>
>>>
[quoted text clipped - 23 lines]
> function parameters within the same class instead of using class
> variables.

Maybe you should look into EJB (Enterprise Java Beans), and session beans in
particular.

/Jimi
Pep - 24 Nov 2005 09:29 GMT
Jimi Hullegrd wrote:

>> <snip>
>>>>
[quoted text clipped - 30 lines]
>
> /Jimi

It's not really a large enough system to justify using EJB.  It will result
in around 25 forms and 35 servlets with 6 beans, so Tomcat is more than
enough though I may extend to struts and hibernate later.

Cheers,
Pep.
Andrea Desole - 23 Nov 2005 13:45 GMT
> I have a servlet application running in Tomcat that uses jsp forms and java
> classes. I use session attributes to to preserve data across the session
[quoted text clipped - 22 lines]
>
> The only way I can clear this ArrayList is to restart the Tomcat container!

It sounds too strange to be a Tomcat bug. It's always possible, of
course, but my first guess in these cases is always an error in the
code, unless you are using other frameworks besides plain servlets and
jsps. Tomcat is usually quite stable.
It's not really clear to me how your code works. The biggest question
probably is related to how your search works, and the relationship with
these session attributes. What I would suggest is to take your code,
remove what you don't need (like all the sql queries), make it as simple
as possible, and post it here. If I understand correctly it should be
one or two jsps and one or two servlets. It's not unlikely that, while
you are doing that, you will find the cause of your problem.
Pep - 23 Nov 2005 13:54 GMT
>> I have a servlet application running in Tomcat that uses jsp forms and
>> java classes. I use session attributes to to preserve data across the
[quoted text clipped - 36 lines]
> one or two jsps and one or two servlets. It's not unlikely that, while
> you are doing that, you will find the cause of your problem.

I am more than happy to accept that it is my code that is at fault rather
than Tomcat.

There are no other frameworks involved here so I did not expect these sort
of errors.

I will have to isolate the servlet and jsp's that are invloved in this part
of the system to be able to send them to this ng.  As you say I may find
the problem in doing that.

More to follow ...

Cheers,
Pep.
Pep - 23 Nov 2005 14:31 GMT
<snip>

> It's not really clear to me how your code works. The biggest question
> probably is related to how your search works, and the relationship with
[quoted text clipped - 3 lines]
> one or two jsps and one or two servlets. It's not unlikely that, while
> you are doing that, you will find the cause of your problem.

Unfortunately isolating the code did not solve the problem for me.

So you need a table in the mysql database called t_Agent that has the
FirstName and LastName columns, varchar(32) will do for these. My current
table has 7 users all with the surname of Smith.

If you start with PEPagents.jsp and fill in a search string such as Smith in
the surname and press the search button you will get passed to the search
results form with correct list of users.

If you then go back in the browser and execute the search again you will end
up with a list that is twice the size of the original list and the entries
will be duplicated such that the original list has been appended with the
same list again.  This happens repeatedly.

If you then close the browser and start all over again, the same thing will
happen in that the list will keep grwoing in size by appending the search
results to the end of the previous list.

If you open another browser and therefore a new session you end up with the
extended list in the new browser!

I do not know what is causing this or what to do to prevent this. The only
way to clear the list os to restart the Tomcat container.

The main servlet
================
package core;

// Import the standard java classes
import java.io.*;
import java.util.*;
// Import the servlet classes
import javax.servlet.*;
import javax.servlet.http.*;
// Import the java sql classes
import java.sql.*;
// Import the packages own classes
import core.beans.Pep;

public class PEPagentEditor extends HttpServlet
{
       private Pep agentObject;
       private String errorString;
       private ArrayList agentArray = new ArrayList();

       public void doGet(HttpServletRequest request, HttpServletResponse response)
               throws ServletException, IOException
       {
               doPost(request, response);
       }

       public void doPost(HttpServletRequest request, HttpServletResponse
response)
               throws ServletException, IOException
       {
               errorString = "";

               // Get the session object
               HttpSession session = request.getSession();

                               Pep agentEditor = new Pep();

                               boolean searchingForUsers = (request.getParameter("buttonSearch") !=
null);
                               boolean creatingNewUsers = (request.getParameter("buttonNew") != null);
                               String userFirstName = request.getParameter("userFirstName");

                               if (userFirstName != null)
                                       // Set the agent editor first name
                               {
                                       agentEditor.setFirstName(userFirstName);
                               }

                               String userLastName = request.getParameter("userLastName");

                               if (userLastName != null)
                                       // Set the agent editor last name
                               {
                                       agentEditor.setLastName(userLastName);
                               }

                                       searchForUser(agentEditor);

                               if (errorString.equals("") && (agentArray.size() != 0))
                                       // No errors so display the users
                               {
                                       session.setAttribute("agentArray", agentArray);
                               
getServletConfig().getServletContext().getRequestDispatcher("/PEPsearchResults.jsp").forward(request,
response);
                               }

               if (!errorString.equals(""))
                       // Guess a error occurred
               {
                       // Add the error string
                       session.setAttribute("errorString", errorString);
                       // Remove the agent array so that we don't recursively fill it up.
                       session.removeAttribute("agentArray");

                       // Branch to the login page, because we have to go somewhere
               
getServletConfig().getServletContext().getRequestDispatcher("/PEPagents.jsp").forward(request,
response);
               }

       }

       private void searchForUser(Pep agentEditor)
       {

               try
               {
                       // Create the database url which is <driver type:database
type://hostname/database name>
                       String databaseUrl = "jdbc:mysql://localhost/TestDB";
                       // Load the database driver
                       Class.forName("com.mysql.jdbc.Driver");
                       // Create the datbase connection
                       Connection sqlConnection = DriverManager.getConnection(databaseUrl,
"user", "password");
                       // Create the sql statement
                       Statement sqlStatment = sqlConnection.createStatement ();
                       // Execute the query, storing the results in a result
                       String sqlQuery = "select LastName, FirstName from t_Agent where LastName
like '"
                                       +
                                       agentEditor.getLastName()
                                       +
                                       "%'";
                       ResultSet sqlResultSet = sqlStatment.executeQuery(sqlQuery);

                       int numberOfColumns = sqlResultSet.getMetaData().getColumnCount();

                       if (numberOfColumns != 2)
                               // There is an error here as we should only get 2 columns
                       {
                               errorString += "<p>Login was unsuccessful because a incorrect number of
columns received!";
                       }
                       else
                       {

                               while (sqlResultSet.next())
                                       // handle all the rows returned
                               {
                                       Pep agentFound = new Pep();
                                       agentFound.setLastName(sqlResultSet.getString(1));
                                       agentFound.setFirstName(sqlResultSet.getString(2));
                                       agentArray.add(agentFound);
                               }

                       }

                       sqlResultSet.close();
                       sqlStatment.close();
                       sqlConnection.close();
               }
               catch(ClassNotFoundException exception)
               {
                       errorString += "java class not found error: " + exception.getMessage();
               }
               catch(SQLException sqlException)
               {

                       while (sqlException != null)
                       {
                               errorString += "<p>SQL Exception:  " + sqlException.getMessage();
                               sqlException = sqlException.getNextException ();
                       }

               }

       }

}

the main jsp
============
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- Handle the session attributes -->
<%
       String errorString = (String)session.getAttribute("errorString");
       session.removeAttribute("agentArray");
%>
<HTML>
       <BODY BGCOLOR="#FDF5E6">
               <CENTER>
                               <FORM method=POST ACTION=/servlet/core.PEPagentEditor>
                                       Surname:
                                       <INPUT TYPE="TEXT" NAME="userLastName" VALUE="">
                                       <P>
                                       Christian:
                                       <INPUT TYPE="TEXT" NAME="userFirstName" VALUE="">
                                       <p>
                                       <input type=SUBMIT name=buttonSearch value="SEARCH">
                                       <p>
                                       <input type=SUBMIT name=buttonNew value="NEW">
                               </FORM>
               </CENTER>
<p> <% if (errorString != null){ %>
<p> <%= errorString %>
<p> <% } %>
<p><b><u>Session attributes</u></b>
<%
       java.util.Enumeration attributeNames = session.getAttributeNames();

       while (attributeNames.hasMoreElements())
       {
               String attributeName = (String)attributeNames.nextElement();
%>
       <p> <%= attributeName %>
<%
       }
%>
       </BODY>
</HTML>
<!-- Clear up the session attributes -->
<%
       session.removeAttribute("errorString");
       // It is possible that this already exists if the user has pressed a back
key in the browser so we need to remove it
       session.removeAttribute("agentArray");
%>

The search results jsp
======================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<jsp:useBean id="agentArray" scope="session" class="java.util.ArrayList"/>
<!-- Handle the session attributes -->
<%
       String errorString = (String)session.getAttribute("errorString");
%>
<HTML>
       <BODY BGCOLOR="#FDF5E6">
               <CENTER>
                               <FORM method=POST ACTION="/servlet/core.PEPagentSelectedResult">

                                       <SELECT name=agentSelected size=1>
                                               <% for (int arrayElement = 0; arrayElement < agentArray.size();
arrayElement++) {%>
                                                       <% core.beans.Pep agentFound =
(core.beans.Pep)agentArray.get(arrayElement); %>
                                                       <OPTION value= <%= arrayElement %> > <%= agentFound.getLastName() %>
<%= agentFound.getFirstName() %>
                                               <% } %>
                                       </SELECT>
                                       <P>
                                       <INPUT TYPE="SUBMIT" VALUE="OPEN" NAME=openButton>
                               </FORM>
               </CENTER>
<p> <% if (errorString != null){ %>
<p> <%= errorString %>
<p> <% } %>
<p><b><u>Session attributes</u></b>
<%
       java.util.Enumeration attributeNames = session.getAttributeNames();

       while (attributeNames.hasMoreElements())
       {
               String attributeName = (String)attributeNames.nextElement();
%>
       <p> <%= attributeName %>
<%
       }
%>
       </BODY>
</HTML>
<!-- Clear up the session attributes -->
<%
       session.removeAttribute("errorString");
%>

The bean
========
package core.beans;

public class Pep
{
       private String lastName;
       private String firstName;

       public Pep()
       {
               setLastName("");
               setFirstName("");
       }

       public Pep(
                       String lastName,
                       String firstName
                   )
       {
               setLastName(lastName);
               setFirstName(firstName);
       }

       public void setLastName(String lastName)
       {
               this.lastName = lastName;
       }

       public String getLastName()
       {
               return(lastName);
       }

       public void setFirstName(String firstName)
       {
               this.firstName = firstName;
       }

       public String getFirstName()
       {
               return(firstName);
       }

}


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.