9.
Cookies and a Shopping Cart
Introduction
Cookies have a number
of uses for Web application developers and one of them is to track user
sessions. Cookies originate on the server, where they are sent as instructions
in the header of the HTTP response. In this chapter, we will see how Cookies
are put to use in conjunction with JSP. You will also be shown how a shopping
cart can be created.
Remember that Java
Server Pages are first turned into a servlet. In case there are any errors in
your JSP script then they too are seen in the servlet. You may not see any
error messages at this point but when you try to run the servlet and display
the output in a browser, you will see the errors. You may get two types of errors.
c1.jsp
<html>
<body>
<%! int i=62745435354354353454354353454354353453454353434543543534543; %>
<% out.println(i); %>
</body>
</html>
Consider this example
where the variable i has been initialized to a very large number. The question
here is, will the JSP engine give an error while generating a servlet or will
it show an error while displaying the output?
---------------
public class jsp_0005cc_00031_0002ejspc1_jsp_1 extends HttpJspBase {
static char[][] _jspx_html_data = null;
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\c1.jsp”;from=(2,3);to=(2,71)]
int i=62745435354354353454354353454354353453454353434543543534543;
// end
---------------
The browser shows you
just a simple error whereas the web server DOS window tells you in detail what
the error is.
Whenever you have a
page directive ‘buffer=kb’, it should be a number because kb will be passed as
a parameter, so when the servlet is compiled it gives an error.
c2.jsp
<%@ page buffer=”kb” %>
This shows the same
error as seen earlier. A bit of showing off now. Here we have a class called
JSPTest.
c3.jsp
<%! public class JSPTest {
public String getName()
{ return “JSPTest”; }
class Inner extends JSPTest {
public String getName()
{ return “Inner”;
}
}
}
%>
<% JSPTest jspTest = new JSPTest();
JSPTest.Inner inn = jspTest.new Inner();
out.println(“ Base name: “ + jspTest.getName());
out.println(“ Inner name: “ + inn.getName());
%>
-----------------
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\c3.jsp”;from=(0,3);to=(10,0)]
public class JSPTest {
public String getName() {
return “JSPTest”;
}
class Inner extends JSPTest {
public String getName() {
return “Inner”;
}
}
}
// end
out.print(_jspx_html_data[1]);
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\c3.jsp”;from=(11,2);to=(15,0)]
JSPTest jt = new JSPTest();
JSPTest.Inner inn = jt.new Inner();
out.println(“ Base name: “ + jt.getName());
out.println(“ Inner name: “ + inn.getName());
// end
--------------
Output:
Base name: JSPTest Inner name: Inner
C3.jsp has a public
class named JSPTest. This class has a function named getName that returns a
string. The string here is JSPTest. This class contains another class, which
extends the same class. Class Inner is within JSPTest and it extends JSPTest.
This is all legal. These types of classes are called inner classes. If Inner is
an inner class then JSPTest should be an outer class! This is in one block of
the script. In the next block, ‘jt’ is a variable that looks like JSPTest.
‘inn’ is another variable that looks like JSPTest.Inner. You can refer to this
class because inner is a class in JSPTest. In C++, they are called Nested
Classes. jspTest.new inner() is used to
initialize inn.
It is of significance
to note that instead of ‘new’ we have
used ‘jt.new’. new is now part of jt. new ( ) is used to create the object and
thus call the constructor. Therefore every time you have a class within a
class, the outer class has its own new to create the inner classes. The
function in the base class ‘getName’ returns JSPTest whereas the one in the
inner class returns Inner. This has nothing to do with JSP. All Java code that
you write in a Java program can be written in JSP too.
In one of the previous
chapters, we tried the bean example where we clicked on a link and went to
another page. This can be done in another way by using jsp:forward. This will
also take us to another page and the same rules apply.
c4.jsp
<html>
<jsp:plugin type=”applet” code=”zzz.class” width=”160" height=”150" codebase=”/examples/jsp” jreversion=”1.2" >
<jsp:fallback>
Hell
</jsp:fallback>
</jsp:plugin>
<p>
Bye
</body>
</html>
The code of zzz.java
is in c:\jswdk-1.0.1\examples\jsp
zzz.java
import java.awt.*;
import java.applet.*;
public class zzz extends Applet
{
int x,y;
public void init()
{
x = 10 ; y = 20;
}
public void paint ( Graphics g)
{
g.drawString(“Hi “, x , y);
}
public boolean mouseDown(Event e, int x1 , int y1)
{
x = x1 ; y = y1;
return true;
}
}
>javac zzz.java
You can put any object
you want along with jsp:plugin. A JSP page can have any plugin. Here we are
giving type=applet, code=zzz.class along with the width and the height. In
order to refresh your memory, the attribute width and height are given because
the applet tag requires us to do so. This has already been explained in the
first chapter. The jreversion is the version number of the Java runtime engine
and the codebase attribute is the location from where the class file is to be
picked up. In our case ‘/’ is the JavaWebserver root directory and from there
we are pointing to the examples/jsp subdirectory where the class file resides.
Jsp:fallback will be looked at only when the object or the plugin statement gives an error. This is a lot like the ‘try-catch’ in Java. There are many types and applet is just one of them. A list of all the types can be found in the documentation. Just another way to add more content to the JSP page.
--------------------
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\c4.jsp”;from=(1,0);to=(6,13)]
/*Code generated for plugin*/
out.println (“<OBJECT classid=\”clsid:8AD9C840-044E-11D1-B3E9-00805F499D93\” width=\”160\” height=\”150\” codebase=\”http://java.sun.com/products/plugin/1.2.2/jinstall-1_2_2-win.cab#Version=1,2,2,0\”>”);
out.println (“<PARAM name=\”java_code\” value=\”zzz.class\”>”);
out.println (“<PARAM name=\”java_codebase\” value=\”/examples/jsp\”>”);
out.println (“<PARAM name=\”type\” value=\”application/x-java-applet;version=1.2\”>”);
out.println (“<COMMENT>”);
out.print (“<EMBED type=\”application/x-java-applet;version=1.2\” width=\”160\” height=\”150\” pluginspage=\”http://java.sun.com/products/plugin/\” java_code=\”zzz.class\” java_codebase=\”/examples/jsp\” >”);
out.println (“<NOEMBED>”);
out.println (“</COMMENT>”);
out.println (“Hell \r\n”);
out.println (“</NOEMBED></EMBED>”);
out.println (“</OBJECT>”);
// end
------------------
The html file received
by the browser is as follows
<html>
<OBJECT classid=”clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" width=”160" height=”150" codebase=”http://java.sun.com/products/plugin/1.2.2/jinstall-1_2_2-win.cab#Version=1,2,2,0">
<PARAM name=”java_code” value=”zzz.class”>
<PARAM name=”java_codebase” value=”/examples/jsp”>
<PARAM name=”type” value=”application/x-java-applet;version=1.2">
<COMMENT>
<EMBED type=”application/x-java-applet;version=1.2" width=”160" height=”150" pluginspage=”http://java.sun.com/products/plugin/” java_code=”zzz.class” java_codebase=”/examples/jsp” ><NOEMBED>
</COMMENT>
Hell
</NOEMBED></EMBED>
</OBJECT>
<p>
Bye
</body>
</html>
Click anywhere and you
will find the word ‘hell’ following the click. All that the servlet does here
is sends across the html file. Since this file has the applet tag, the browser
asks for the applet. So the JSP engine sends the tags across with the
attributes. The browser receives it and works as per the tags in the file.
c5.jsp
<html><jsp:forward page=”e1.jsp” />
</html>
--------------------
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\c5.jsp”;from=(1,0);to=(1,29)]
if (true) {
out.clear();
pageContext.forward(“e1.jsp”);
return;
}
// end
------------------
You will directly come
to another page, in this case you will come to e1.jsp.
Let’s
see how we can call a servlet from JSP and then have the servlet load another JSP
file.
c.jsp
<html>
<jsp:forward page=”/servlet/yyy” />
</html>
c.jsp is located in
c:\jswdk-1.0.1\examples\jsp subdirectory. It forwards to another page that the
servlet yyy generates.
yyy.java is located in
c:\jswdk-1.0.1\webpages\web-inf\servlets. To load this servlet the url should
be given as http://127.0.0.1:8080/examples/jsp/c.jsp.
yyy.java
import javax.servlet.*;
import javax.servlet.http.*;
public class yyy extends HttpServlet {
public void doGet (HttpServletRequest request, HttpServletResponse response)
{
try {
request.setAttribute (“servletName”, “vijay”);
ServletConfig a = getServletConfig();
ServletContext b = a.getServletContext();
RequestDispatcher c = b.getRequestDispatcher(“/jsp/c6.jsp”);
c.forward(request, response);
} catch (Exception ex) { ex.printStackTrace (); }
}
}
c6.jsp will be in the
same directory as c.jsp i.e. c:\jswdk-1.0.1\examples\jsp.
c6.jsp
<html>
invoked by <% out.print (request.getAttribute(“servletName”).toString()); %>
</html>
c.jsp will load the
servlet yyy, where the function doGet is called. request.setAttribute will set
the attribute named servletName to vijay. This is how we can create a variable
within the servlet. Now anyone who has access to the servlet can access this
variable vijay. This implies that any servlet can access the attribute
‘servletName’. Instead of calling it ‘servletName’ you could have called it
aaa.
‘a’ is a servletconfig
which is initialized to the return value of getServletConfig. It is a function
in HttpServlet. This has one member named ServletContext. The context in which
the servlet is acting is the ServletContext and this function’s return value is
stored in b. When we call getRequestDispatcher from ServletContext, it will
return a requestdispatcher and the parameter passed to this function is the
page we wish to view. Here, we give /jsp/c6.jsp, which will load c6.jsp from
the current directory-jsp and then finally, we say forward with our request and
response. Now c6.jsp will be called. This JSP file will be compiled on the fly
i.e. it will be converted into a servlet. In c6.jsp, we have
request.getAttribute for servletName and hence it will give us vijay. This is how servlets communicate internally.
In short, we have
moved from one JSP page ‘c.jsp’, which became a servlet, to another servlet yyy
which called a third servlet of c6.jsp and finally you see vijay displayed on
the screen. Note that the first and the third servlet were originally JSP based
Let’s consider a
simple bean.
c7.jsp
<jsp:useBean id=”cb” scope=”session” class=”yyy.zzz” />
<jsp:setProperty name=”cb” property=”*” />
hi
c7.jsp starts with
jsp:usebean and the id is given as cb. The scope here is not important. The
name of the class is yyy.zzz.
Go to the web-inf
directory and within the jsp\beans subdirectory create a new subdirectory yyy.
Create a Java file called zzz.java here. It must contain the following code:
c:\jswdk-1.0.1\examples\Web-inf\jsp\beans\yyy>edit zzz.java
zzz.java
package yyy;
public class zzz
{
public void setxx(String a)
{
System.out.println(“setxx “ + a);
}
public void setyy(String a)
{
System.out.println(“setyy” + a);
}
public String getxx()
{
System.out.println(“getxx”);
return “”;
}
public String getyy()
{
System.out.println(“getyy”);
return “”;
}
}
run it in the browser
as
http://127.0.0.1:8080/examples/jsp/c7.jsp?xx=hi&yy=bye
The property for the
bean cb is set by giving property=’*’. This refers to the properties that are
given in the form of name=value data in the url. Since the address given in the
address bar has a ‘?’ followed by xx=aaa&yy=bbb, the properties to be set
will be that of xx and yy. So the JSP engine will call setxx and setyy with aaa
and bbb in the Java Bean. If you had
just given xx=aaa then only setxx would be called. If you are a good Bean
designer, you will first find out the number of parameters you will be
accepting and then accordingly create the properties in the Bean. So if you are
accepting 7 parameters, you must create 7 properties with the same name in your
Bean. Every property in the Bean will have get and set preceding the property
name. ‘*’ in the property will initialize all the properties in the Bean. You
don’t have to set all the properties yourself and this example proves that.
The next program has
been taken directly from the examples provided by Sun Microsystems. Here, we
are considering an HTML file ‘aa.html’ within which there is code for creating
a listbox. This file is to be placed in
the examples/jsp subdirectory of jswdk-1.0.1.
aa.html
<html>
<form method=POST action=”http://127.0.0.1:8080/examples/jsp/c8.jsp”>
Add Item:
<SELECT NAME=”item”>
<OPTION>Beavis & Butt-head Video collection
<OPTION>X-files movie
<OPTION>Twin peaks tapes
</SELECT>
<INPUT TYPE=submit name=”submit” value=”add”>
<INPUT TYPE=submit name=”submit” value=”remove”>
</form>
</html>
We are create one
listbox with three options. The first one is shown by default but you are
allowed to choose any of them. When you click on the submit button the option
selected will be given to the name ‘item’. You will notice that here we have
two submit buttons here, with the values add and remove respectively.
Irrespective of the button clicked, the file that will be called is c8.jsp,
which for the moment is on the same hard disk that we are operating from. The
method given is post, items will be equal to the option selected and submit
will be equal to either add or remove, these will go as parameters to the JSP
file.
Under normal
circumstances submit isn’t added as part of the parameter list, this happens
only when there are two submits in the form. Once you click on submit, c8.jsp
will be called. c8.jsp is stored in c:\jswdk-1.0.1\examples\jsp.
c8.jsp
<jsp:useBean id=”cart” scope=”session” class=”ppp.qqq” />
<jsp:setProperty name=”cart” property=”*” />
<%
cart.processRequest(request);
%>
<FONT size = 5 COLOR=”#CC0000">
<br> You have the following items in your cart:
<ol>
<%
String[] items = cart.getItems();
for (int i=0; i<items.length; i++) {
%>
<li> <%= items[i] %>
<%
}
%>
</ol>
</FONT>
<hr>
<%@ include file =”aa.html” %>
</html>
qqq.java
package ppp;
import javax.servlet.http.*;
import java.util.Vector;
import java.util.Enumeration;
public class qqq {
Vector v = new Vector();
String submit = null;
String item = null;
private void addItem(String name) {
v.addElement(name);
}
private void removeItem(String name) {
v.removeElement(name);
}
public void setItem(String name) {
item = name;
}
public void setSubmit(String s) {
submit = s;
}
public String[] getItems() {
String[] s = new String[v.size()];
v.copyInto(s);
return s;
}
public void processRequest(HttpServletRequest request) {
if (submit == null)
addItem(item);
if (submit.equals(“add”))
addItem(item);
else if (submit.equals(“remove”))
removeItem(item);
reset();
}
private void reset() {
submit = null;
item = null;
}
}
The bean that we are
using is called ppp.qqq. At first the properties are set so setItem and
setSubmit are called which initialize item and submit to the values from the html
file after the user clicked on add. Then the cart.processRequest function in
the bean is called with request as a parameter. (Remember request, like ‘out’,
is a predefined object)
If you click on add,
then submit will have the value add. Hence the addItem function will be called
with item as a parameter. In addItem, we have only one line, which is
v.addElement. v is a vector and it has a function named addElement. A vector is like an array, made up of
similar objects. Using v.addElement we add the item name to the vector.
String[] items = cart.getItems();
for (int i=0; i<items.length; i++) {
%>
<li> <%= items[i] %>
In order to display
the selected items, getItems in the Bean is called. This function copies
elements of the vector into a string array, which is then returned. Hence items
in the JSP file will now contain these elements. As you already know, every
string contains a length, which gives you the number of elements in the string.
Thus items.length will now be the number of elements in the vector. The for
loop is used to display each member. In order to display it as a bulleted list
we have used li with <%=items[i]’. i is used along with the items to display
every element.
v.size represents the
number of elements in the vector. For example, if you have 5 elements then
v.size will give the value 5. v.copyInto will copy from the vector into a
string array named s. Then s, an array of strings, is returned.
This is how you can
build a shopping cart. The concept of keeping the connection alive with a
session in the servlet facilitates the creation of a virtual shopping mall.
At this point start
afresh. There will be now two separate sessions. In case you had used
application instead of session, the process would have run forever for every
new user. If the session was request or page then this exercise would not have
been valid. The best way to test the Bean is by trying out these other scopes.
Cookies
The following example
introduces the concept of Cookies.
e25.jsp
<%@ page session=”true” %>
<%
Integer num = new Integer(100);
session.putValue(“num”,num);
String url = response.encodeURL(“a1.jsp”);
%>
<a href=’<%=url%>’> a1.jsp </a>
a1.jsp
<%@ page session=”true” %>
<%
Integer i = (Integer)session.getValue(“num”);
out.println(“Num is “ + i);
%>
In Internet Explorer,
go to the menu option Tools and choose Internet Options. Then select the tabbed
dialog option Security and click on the button labelled Custom Level. Finally, select prompt for the
Cookie options. You must enable cookies in your browser. Also, select ‘prompt’for the Cookies
per-session option. You will now know when a cookie comes over since the
browser will ask you for confirmation.
A Cookie is stored as
a file on disk. It contains a certain finite number of characters and is very
small in size. The second important point to remember is that the cookie is
transferred as a header. It is sent as the cookie name and it’s value.
The first line in the
example is page session=true. It is not necessary to include this line because
it is true by default. Then a variable named num is created which looks like
integer. While calling the constructor, 100 is passed as a parameter. So num
now holds the number 100. The next line in the script is session.putValue. This
function putValue will create a variable named num and give it a value 100.
Then we create a string variable called url that will be assigned the absolute
address of a1.jsp. Finally <a
href=’%url%’>a1.jsp</a> will be evaluated to <a
href=’http://127.0.0.1:8080/examples/jsp/a1.jsp’>a1.jsp</a>” as it is
pure html.
a1.jsp has a variable
i of type integer. This variable is initialized to the return value of
session.getValue(num). Remember, num was a variable created by session.putValue
and it was initialized to 100. This object session remains active across the
JSP pages and thus getValue of num returns 100.
A user interacts with
the web server in sessions. Thus, the session object allows you to create a
variable in one file using putValue. You can then use this variable on another
page. This method will work only if the page session is initialized to true.
This is how you can
transfer values from one file to another. Hence a1.jsp will print the value of
i as 100.
What are Cookies and
how do Cookies work? Aha! You all know what Cookies are and how well they work
for the stomach, but we are interested in a new type of Cookie, freshly baked
from the Java shelf! So far you’ve only
smelt the Cookie, now you get to taste it!
The first time you
connect to the web server, it will send you a cookie. As we have changed our
cookie option to prompt, we will see a message box where we will click on ‘more
info’. Here we will be told that our cookie name is SESSIONID. It expires at
the End of session and also the Data is To1011mC8999595236320718At. The web
server sends a header with Set-Cookie: SESSIONID = To1011mC8999595236320718At.
Now if you start another browser session the cookie name will be the same but
the data will be To1012mC22314797589282154At i.e. it will be different. Each
time a browser receives a cookie, it sends a header to the server the next time
it connects. This header contains Cookie: SESSIONID =
To1011mC8999595236320718At. This is how the web server can recognize one
browser instance from another. To sum up, the web server starts by sending a
cookie and the browser will send the same cookie back when it connects to the
server again. The cookies are stored on your hard disk.
Num is null
If you disable cookies
then you will get the output shown above as there is no way to distinguish one
browser instance from another.
A Cookie is a small amount of information
which is sent by a servlet to the web browser. The browser saves this
information on the hard disk and later on it can also be sent back to the
server. A Cookie’s value can uniquely identify a client. Hence Cookies are
commonly used for session management. A Cookie has a name, a single value and
it has attributes like comment, path, domain qualifiers, maximum age and
version number. A large number of web browsers have bugs in how they handle the
optional attributes, so please use them sparingly. They improve the
interoperability of the servlet.
Normally, a Cookie is
sent to the browser one at a time and the browser is expected to support 20
Cookies for each web server, 300 Cookies in total and it may limit the Cookie
size to 4k each. The browser is sent Cookies in the header and it returns
Cookies to the servlet by adding fields to the http request header as mentioned
earlier. Several Cookies might have the same name but different path
attributes. Cookies affect the caching of the web pages that use them because
HTTP 1.0 doesn’t cache the pages with Cookies. There are two versions of the
Cookies, version 0 is by Netscape and version 1, which is documented in
rfc2109, is the original one. By default, Cookies are created in version 0 to
ensure the best operability and the Cookies class implements cloneable. By
default, all Cookies are returned to the server that sent them. A Cookie is
sent to the browser by the servlet in the headers. That means that if the
browser ever receives a Cookie from the server then each time it connects to
the server, it will send the cookie in the header.
C:\jswdk-1.0.1\webpages\web-inf\servlets> edit c1.java
c1.java
import java.io.*;import javax.servlet.*;
import javax.servlet.http.*;
public class c1 extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)throws IOException, ServletException
{
Cookie c;
c = new Cookie(“zz7”, “mukhi”);
res.addCookie(c);
PrintWriter out = res.getWriter();
out.println(“Hi”);
}
}
Let’s consider this
example. Here, c is an object that looks like Cookie. When we say c=new Cookie,
we are passing two parameters to the constructor; one is a name ‘zz7’, which
should be the name our cookie and the
other is a value ‘mukhi’ i.e. the value of the cookie. Basically, we’ve created
an object that looks like Cookie. res looks like HttpServletResponse and addCookie will add this cookie. The
servlet uses HttpServletResponse whenever it wants to send some information to
the server. All that the server does is, creates a header with the header
variable Set-Cookie: and the value is given as zz7=mukhi.
Set-Cookie: zz7=mukhi
If you haven’t enabled
the Cookies option in your browser to Prompt, we suggest you do it now.
This program is called
when you load it in the browser. Give the url as
http://127.0.0.1:8080/servlet/c1. On doing so, a message box will be displayed.
Before clicking on ‘Yes’ select ‘More Info’. It will tell you that the Cookie
name is zz7 and below that it will show mukhi. This proves that your browser
did receive a Cookie. Having understood the above program, let’s look at the
next program.
c2.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class c2 extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException
{
PrintWriter out = res.getWriter();
Cookie[] c = req.getCookies();
for (int i = 0; i < c.length; i++)
out.println(“cookie “ + c[i].getName() + “=” + c[i].getValue());
out.println(“Hi”);
}
}
cookie zz7=mukhi Hi
We sent one cookie and
we received one cookie.
Here, c is an array of
Cookies. request.getCookies returns an array of Cookies. So, in the for loop we
have i=0; i < c.length and then i++. Using getName and getValue, the name of
the Cookie and the value given to it are printed. In our case c.length will be
1 because we have sent only one Cookie from the server. You can also send two
Cookies at the same time. The next program demonstrates this.
c3.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class c3 extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException
{
Cookie c;
c = new Cookie(“zz9”, “mukhi”);
c.setComment(“Will this get dropped?”);
c.setMaxAge(100);
c.setPath(req.getServletPath());
c.setSecure(true);
res.addCookie(c);
c = new Cookie(“zz10”, “mukhi1”);
c.setComment(“Will this get dropped?1”);
c.setMaxAge(10);
c.setPath(req.getServletPath());
res.addCookie(c);
PrintWriter out = res.getWriter();
out.println(“H i” + req.getServletPath());
}
}
In this program we
have included Comment, which are some lines of text that you may want to add.
setMaxAge decides how long the Cookie lives and setSecure is to use https -
secure sockets layer to send this Cookie across. setPath means you are sending
your computer path with your name and req.getServletPath will give the
following : /examples/servlet/zzz.
Now click on ‘More Info’
and you will observe that the other values, which were not filled in earlier,
are now filled in. setMaxAge indicates the time period that the Cookie will be
alive for. setPath specifies the path for the cookie to which the client should
return the cookie. A cookie is visible to all pages in the directory you
specify, and its subdirectorys. A Cookie’s path must include the servlet that
sent the Cookie. For example, /catalog makes the Cookie visible to all the
Cookies on the server under /catalog.
As we set the
setMaxAge, the cookies ‘expires’ property now gives you an actual date and
time. It is no longer a session cookie and netscape stores this information in
a file named cookies.txt. The header now has an Expires=date added to it.
In order to do so, use
setPath and then use setVersion. If you specify the version as 0, the Cookie
should comply with the original Netscape specification, if it is 1, then it
should comply with rfc2109. Since Cookies are returned to a server, all
servlets running within a server share Cookies. The next program shows how the
domain, the path and the version can be retrieved.
c4.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class c4 extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException
{
PrintWriter out = res.getWriter();
Cookie[] d = req.getCookies();
for (int i = 0; i < d.length; i++)
{
Cookie c = d[i];
out.println(“cookie “ + c.getName() + “=” + c.getValue());
out.print(c.getComment() + “ “ + c.getDomain() + “ “ + c.getMaxAge());
out.println(“ “ + c.getPath() + “ “ + c.getSecure() + “ “ + c.getVersion());
}
out.println(“Hi”);
}
}
In this example, the
first Cookie comes over because you didn’t set the path, the next two Cookies
don’t come over because you have set the path and the path is different.
But how can one write
a program that determines whether the Cookies have been disabled or enabled?
Run the following program, c5.java.
c5.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class c5 extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException
{
Cookie c;boolean h = false;
String p = req.getParameter(“ppp”);
if (p == null) {
c = new Cookie(“vij4”, “hi”);
res.addCookie(c);
res.sendRedirect( “/servlet/c5?ppp=no” );
}
else if (p.equals(“no”)) {
h = false;
Cookie[] d = req.getCookies();
for (int i = 0; i < d.length; i++) {
if (d[i].getName().equals (“vij4”)) {
if (d[i].getValue().equals(“hi”)) {
h = true;
break;
}
}
}
if ( h == true)
res.sendRedirect( “/servlet/c6?aa=yes” );
else
res.sendRedirect( “/servlet/c6?aa=no” );
}
}
}
c6.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class c6 extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)throws IOException, ServletException
{
PrintWriter out = res.getWriter();
String s = (String ) req.getParameter(“aa”);
out.println(s);
}
}
c is a Cookie and h is
a boolean with a value ‘false’. p is a String that is initialized to the value
given to ppp. ppp gets a value only when the user sends the url as
http://127.0.0.1:8080/servlet/c5?ppp=xxx. Since we haven’t given it in this
manner, p will be null. The if condition becomes true and the control passes to
the if statement. c is a Cookie where the variable vij4 is given the value
‘hi’. This is added to the response and sendRedirect will redirect the browser
to pick up another file from the disk. In the meantime the server will send the
cookie to the browser and we can see that the value of the cookie vij4 is hi.
The file is c5, the same servlet, but now with ppp having a value ‘no’.
Remember, the cookie is sent to the browser and redirect wrote the new url in
the address bar of IE. The servlet gets called again but now the else
statements are executed. Here, it is first checked whether the value of p is
‘no’. This being true in our case, the statements within if are executed. The
variable h is reinitialized to false and d is now declared as an array of
Cookies.
req.getCookies will
return an array of Cookies. This is given to d. Within the for loop, it is
checked whether a Cookie named vij exists. If there is one, then we break from
the loop after initializing h to the value true. In our case with cookies off,
the name ‘vij4’ does not exist, so h remains false. When the loop terminates,
it is checked whether the value of h is true or false. If it is false, then the
browser is redirected to another servlet c6 with the value ‘no’ given to aa.
The servlet c6 now prints the value ‘no’ on the screen. If the value is ‘yes’,
then the browser supports Cookies, because in that case it would already have a
name ‘vij4’ stored.
c7.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class c7 extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
{
res.setContentType(“text/html”);
PrintWriter out = res.getWriter();
out.println(“<HEAD><TITLE>Current Shopping Cart Items</TITLE></HEAD>”);
out.println(“<BODY>”);
String[] items = req.getParameterValues(“item”);
out.println(“You currently have the following items in your cart:<BR>”);
if (items == null) {
out.println(“<B>None</B>”);
}
else {
out.println(“<UL>”);
for (int i = 0; i < items.length; i++) {
out.println(“<LI>” + items[i]);
}
out.println(“</UL>”);
}
out.println(“<FORM ACTION=\”http://127.0.0.1:8080/servlet/c7\” METHOD=GET>”);
if (items != null) {
for (int i = 0; i < items.length; i++) {
out.println(“<INPUT TYPE=HIDDEN NAME=item VALUE=\”” + items[i] + “\”>”); }
}
out.println(“Would you like to<BR>”);
out.println(“<INPUT TYPE=SUBMIT VALUE=\” Add More Items \”>”);
out.println(“<INPUT TYPE=TEXT NAME=item>”);
out.println(“</FORM>”);
out.println(“</BODY></HTML>”);
}
}
In c7.java, we are
first printing the values of the array ‘items’ of type String. This variable is
initialized to the value in the item parameter i.e. if the url contains
?item=hi , then the items array will contain one member named hi. If after the
? we had item=hi&item=bye, then the items array would have 2 members, hi
and bye. A parameter in a url can have the same name repeated multiple times.
Since we have given the url as http://127.0.0.1:8080/servlet/c7 there is no
parameter value given to this servlet.
Hence no items exist and we see ‘None’ displayed on the screen. The else
block isn’t executed and hence no list is displayed. Then a form is displayed
on the screen. The for loop will not be executed as there are no items.
Now within the text
box, we want you to write aa and then click on the ‘Add More Items’ Button.
req.getParameterValue(item)
will now have the value as item=aa. With Java servlets and the HTTP protocol
you can have items=hi&items=bye given along with the url. Note that you can
have as many values given to the same parameter. getParameterValue will now
give you an array of strings. You can then display all the strings.
The servlet creates an
html file along with a form. We have the input tag with type=hidden name =item
and then the value of items. So if there are 6 items then we will have 6 input
statements and all of them will be hidden. Hidden inputs will not be displayed
on the screen. Now each time you say submit i.e. click on ‘Add More Items’
after writing in the text box, the program specified by action is called.
Finally, we are calling the same servlet c7 and thus you see the same screen
displayed again. This is one way of creating a shopping cart without using
sessions.
View Source
<HEAD><TITLE>Current Shopping Cart Items</TITLE></HEAD>
<BODY>
You currently have the following items in your cart:<BR>
<UL>
<LI>ggg
<LI>ttt
<LI>uuu
</UL>
<FORM ACTION=”http://127.0.0.1:8080/servlet/c7" METHOD=GET>
<INPUT TYPE=HIDDEN NAME=item VALUE=”ggg”>
<INPUT TYPE=HIDDEN NAME=item VALUE=”ttt”>
<INPUT TYPE=HIDDEN NAME=item VALUE=”uuu”>
Would you like to<BR>
<INPUT TYPE=SUBMIT VALUE=” Add More Items “>
<INPUT TYPE=TEXT NAME=item>
</FORM>
</BODY></HTML>
URL
http://127.0.0.1:8080/servlet/c7?item=ggg&item=ttt&item=uuu
A little more on
Sessions......
This example will
explain sessions once more.
C:\jswdk-1.0.1\webpages\web-inf\servlets>edit xxx.java
xxx.java
import java.io.*;
import java.net.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class xxx extends HttpServlet {
int i = 0;
public void doGet(HttpServletRequest
request,HttpServletResponse response) throws
ServletException, IOException {
HttpSession s = request.getSession();
response.setContentType(“text/html”);
PrintWriter out = response.getWriter();
String h=” “;
Integer o,o1;
if (s.isNew()) {
o = new Integer(0);
h = “First Time”;
s.putValue(“acc”, o);
}
else {
h = “Once Again”;
o = (Integer)s.getValue(“acc”);
o = new Integer(o.intValue() + 1);
s.putValue(“acc”, o);
}
out.println(h + “<p>”);
out.println(“id “ + s.getId() + “ <p>”);
out.println(“Creation Time “+new
Date(s.getCreationTime()) + “ <p>”);
out.println(“Time of Last Access “+ new
Date(s.getLastAccessedTime())+”<p>”);
out.println(“Max Inactive Interval “+
s.getMaxInactiveInterval()+”<p>”);
out.println(“getValue “+ s.getValue(“acc”)+”<p>”);
out.println(“Number of Previous Accesses “+o+”<p>”);
String e[];
e = s.getValueNames();
for(int i=0; i <e.length; i++)
out.println(“Names “+e[i]+ “<p>”);
}
}
Output
First Time
id To1015mC6692480998335292At
Creation Time Tue Dec 26 17:45:51 GMT+05:30 2000
Time of Last Access Tue Dec 26 17:45:51 GMT+05:30 2000
Max Inactive Interval -1
getValue 0
Number of Previous Accesses 0
Names acc
After clicking on the
Refresh Button
Once Again
id To1015mC6692480998335292At
Creation Time Tue Dec 26 17:45:51 GMT+05:30 2000
Time of Last Access Tue Dec 26 17:45:51 GMT+05:30 2000
Max Inactive Interval -1
getValue 1
Number of Previous Accesses 1
Names acc
Once the servlet is
loaded, the doGet function is called. A variable ‘s’ that looks like
HttpSession is created. It is initialized to the session object returned by
request.getsession. response.setContentType will set the content type header to
text/html. Now out is a variable that will generate our html file. The variable
‘h’ is of type String and is initialized to a blank space. Also, we have
created two other variables o and o1 of type Integer.
Every object that
looks like session has a function named isNew. This function checks whether the
session has been accessed in the past. At the moment, there has been no value
given in this session, so isNew returns true. When the control enters the if
statement, the variable o is given a value by calling the constructor with one
parameter in Integer. Giving 0 as the value in the constructor will initialize
o to 0.
s.putvalue is one more
function in HttpSession which takes the name of the variable and then the value
to be given to this variable. The variable or the word here is ‘acc’.
Indirectly, acc is given the value 0. ‘h’, which is a string variable, is
assigned the string ‘First time’. At this point the else block will not be
executed.
The values of a few
variables or properties in this session are then displayed.
out.println with h
will display ‘First time’. Then we have s.getId. Every session is given a
unique number. Thus, s.getId will display that unique id. The id is a number
generated at random and is assigned only by the servlet container. It is
implementation dependent. Then s.getCreationTime will return the time in
milliseconds, i.e. the time when you last created the session. This is given to
the Date constructor. This in turn will return a Date object which when
displayed looks like the date format. The same rules apply for
s.getLastAccessedTime. In our case the creation time and the date of last
access will be similar.
MaxInactiveInterval
will tell you how much time has elapsed since you last accessed the session.
When a client doesn’t access a running session within a certain period of time,
the session is invalidated. That means the servlet will discontinue the session.
Here, if you say 10 minutes and do not access the session within 10 min, it
will show a timeout. This is to make sure that the session doesn’t go on
indefinitely. The reason being, a user may decide to visit the Amazon site and
not ‘check out’, he may simply disappear, or go to another site as he may have
changed his mind. Here, if you give -1,
a negative time, then the session doesn’t timeout.
s.getValue will give
you the value of acc which is 0 at the moment. Thus it prints 0 along with the
number of previous accesses, which again is the value of o i.e. 0. Remember,
both are the same.
Session has a function
named getValueNames, which returns an array of Strings for the attributes or
words present in the session. Since it is an array, we put it in a for loop.
The variable i is initialized to 0. The loop will go on till the value of i
reaches the length of the array. In our case, since we have only one attribute,
the control will enter the loop only once, display acc and then quit.
Now, when you click on
the refresh button in IE, the session doesn’t change but if you start a new
copy of the browser then things will change.
When doGet is called
again i.e. when we press refresh, isNew returns false since acc is an attribute
with a value in the session. So now the else block of the if statement is
called. Here the current value of h is changed to ‘Once again’. Then, the value
of acc is retrieved using getValue. The
Integer class has a function named intValue which converts the value to an int.
o is reinitialized to a new value which is the old value plus 1. Finally,
putValue sets acc to this new value.
A session is an
abstract entity created by the servlet. A servlet is loaded once and only once
into memory whereas a session is created each time a new instance of a browser
accesses the site. Thus a session is the same browser or the same user
accessing different parts of the site. A new copy of IE would mean a new user
and hence implies a new session. It is the cookie which distinguish one session
from another.
Using this technique,
you can now create a Shopping Cart. Remember, the servlet is loaded only once
in memory.
Consider the following
illustration- Each time you vist the
Amazon site, if there is a servlet running on Amazon, you will be given a new
session id. The session keeps track of what you buy. This is very similar to
the value of acc, which keeps incrementing and yet remains unique to the
current session. All the attributes are session wise, hence you can now store
all the books that you have purchased in the shopping cart.
The session provides a
way to identify a user across more than one page or a visit to a website. In
effect, you can now store information about the user. Until a client joins a
session isNew() returns true and on joining the session a value is inserted in
that session. The session information is scoped only to the current copy of the
browser. Therefore, the information stored in one session will not be directly visible to another.
Conclusion
In this chapter, you have
seen how a shopping cart can be created.