servlets
General structure of a servlet
import
javax.servlet.*;
import javax.servlet.http.*;
import
java.io.*;
public
class OurServlet extends HttpServlet
{
public void init() throws ServletException
{
/*
Retrieving initialization parameters.
Providing resources to the servlet like database connection.
*/
}
public void destroy()
{
//Releasing resources like closing the database connection.
}
public void doGet/doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException,IOException
{
//Client request processing code.
}
}
Servlet engine loads this class into memory, creates
its instance and calls init method and doGet/doPost methods implicitly. When
the servlet is unloaded, the servlet engine calls the destroy() method.
Web container offers the following support.
1.
Servlet life cycle
management
2.
Concurrency
support.
3.
Communication
support.
When multiple concurrent requests come to the web
container it implements multithreading. This is nothing but concurrency
support. A servlet does not need to talk to the clients to get user data. Web
container provides that support.
Servlet Life cycle:
Servlets are container
managed. The life and death of servlets is under the control of the Servlet
Engine. Servlet engine is developed strictly according to the SERVLET
specification. Our servlet also is written conforming the same specification
and by following the SERVLET API. Therefore the servlet container can manage
the servlet life cycle. The servlet life cycle steps describe the process by
which the servlet container loads, instantiates, unloads and invokes its life
cycle methods.
- The servlet
container loads the servlet class that we developed and deployed into it.
This can happen either at the time of web application start up or on
receiving the client request for the first time.
- The servlet
engine creates the servlet instance.
- Servlet engine
creates the ServletConfig object.
- Servlet engine
calls the init method by supplying ServletConfig object as argument
(Parameterized init method internally calls the zero argument init
method).
- Servlet engine
creates ServletRequest object & ServletResponse objects.
- Servlet engine
calls the public service method and supplies the above two objects as
arguments.
- Within the
public service method these two objects are converted into Http specific
objects and public service method calls protected service method.
- Within the
protected service method client request type is calibrated (GET or POST).
Depending upon the type of request, protected service method calls either
doGet () or doPost(). In one of these methods a servlet developer
implements the client request processing code that involves
i.
Evaluating the
HttpServletRequest object and capture the user input.
ii.
Producing dynamic
data by communicating with the database.
iii.
Building dynamic
web content and sending it to the client using HttpServletResponse object.
- If the
container receives another client request, process starts from step 5.
- When the
container is instructed to keep the servlet out of service (undeployed),
the servlet engine calls the destroy method on the servlet instance just
before the servlet instance is garbage collected.
Web application Development steps:
A servlet is a part of a web application. Therefore, to
write our first servlet and execute it we need to know how to develop and
deploy our web application.
Step 1:
Create a directory structure according to SERVLET specification.
Root directory
WEB-INF
classes
lib
Root
directory name can be any thing. It should have a sub directory “WEB-INF”.
Within this two more sub directories classes & lib.
Step 2:
Web resources development.
A web
application contains HTML documents, image files, jsps, servlets etc. We have
to develop all these resources as per our
application requirement.
Step 3:
Deployment Descriptor Development
Deployment descriptor is an xml file. According to SERVLET
specification, each web application should have one deployment descriptor whose
name should be web.xml. Typical actions
we perform in the DD file are
- Registering
the servlets.
- Creating the
URL mappings for servlets
- Supplying
initialization parameters
- Configuring
the filters
- Specifying the
listeners
- Specifying the
error pages.
- Configuring
the welcome files
- Configuring
the session time outs.
- Registering
the JSP tag libraries
- Configuring
the security constraints etc.
Step 4:
Deploying the web resources & DD file into the web application
In this step, we copy different files of the web
application into the different directories.
·
All the html
documents, jsps and image files directly under the root directory.
·
web.xml into
WEB-INF
·
All the java class
files into classes directory
·
All jar files into
lib directory
Tomcat & web application deployment
For
developing and deploying web applications we need web container software loaded
into our computer system. Tomcat is a web container from Apache Software
Foundation. Once we install Tomcat, it will be installed into an installation
directory Tomcat 5.0. This is known as CATALINA_HOME. This installation
directory will have few sub directories.
webapps: - Into this directory we have to copy our web
application root directory.
bin: - In this directory we have Tomcat server start up
& shut down MS-DOS batch files. By clicking on them either we can start up
Tomcat or shut down it.
Common: - In this directory we have another sub
directory “lib”. In this sub directory we have 2 jar files.
- servlet-api.jar
- jsp-api.jar
We have to set the class path to these files before
compiling our servlet source code. While developing servlets the first file is
used. While jsp development the second jar file is used. After clicking the startup MS-DOS batch file.
Q) Develop and deploy a web application in which an end
user should be able to enter his/her name into a web form. A servlet has to
receive the user name, build a dynamic greeting message addressing the user
with name and send the web page to the web client.
Step 1: - Directory structure creation
greetingapp
WEB-INF
classes
lib
Step 2: - Web resources development.
Source code of the user.html
<HTML>
<BODY BGCOLOR="wheat">
<CENTER>
<FORM
ACTION="http://localhost:8080/greetingapp/greet">
NAME
<INPUT TYPE="text" NAME="greet">
<INPUT
TYPE=submit VALUE="send">
</FORM>
</CENTER>
</BODY>
</HTML>
Servlet source code
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class GreetingServlet extends
HttpServlet
{
public
void doGet(HttpServletRequest request,HttpServletResponse response)
throws
ServletException,IOException
{
String
name=request.getParameter("greet");
String
message="HELLO! "+name;
response.setContentType("text/html");
PrintWriter
outstream=response.getWriter();
outstream.println("<HTML>");
outstream.println("<BODY
BGCOLOR=cyan>");
outstream.println("<H3>
"+message+ "</H3>");
outstream.println("</BODY>");
outstream.println("</HTML>");
outstream.close();
}
}
Step 3:
- Deployment Descriptor (web.xml)
<web-app>
<servlet>
<servlet-name>greeting</servlet-name>
<servlet-class>GreetingServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>greeting</servlet-name>
<url-pattern>/greet</url-pattern>
</servlet-mapping>
</web-app>
Step 4:
- configuring the resources.
greetingapp
user.html
WEB-INF
web.xml
classes
GreetingServlet.class
In order to deploy the web application, copy the root
directory along with all the resources and helper files into the “webapps”
directory of Tomcat installation directory and start the Tomcat.
Launch the browser and type the following URL.
http://localhost:8080/greetingapp/user.html
Q) Web
application in which end-user should be able to enter 2 numbers into the web
form. If add button is clicked, servlet should send the sum of two numbers to
the client. If the subtract button is clicked the difference should be sent to
the client.
Directory structure along with files
computeapp
numbers.html
WEB-INF
web.xml
classes
ComputeServlet.class
After deployment we have to type the
following URL in the browser.
If the end user clicks on “sub” button, the following
result appears.
If the clicked button is “add” the result is as
follows.
numbers.html
<HTML>
<BODY >
<CENTER>
<H1>Numbers entry screen</H1>
<FORM
ACTION="http://localhost:8080/computeapp/compute">
NUMBER
ONE<INPUT TYPE="text" NAME="t1"><BR>
NUMBER
TWO<INPUT TYPE="text" NAME="t2"><BR><BR>
<INPUT
TYPE="submit" NAME="click" VALUE="add">
<INPUT
TYPE="submit" NAME="click" VALUE="sub">
</FORM>
</CENTER>
</BODY>
</HTML>
ComputeServlet.java
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class ComputeServlet extends HttpServlet
{
public
void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException,IOException
{
int
n1=Integer.parseInt(request.getParameter("t1"));
int
n2=Integer.parseInt(request.getParameter("t2"));
int
result=0;
String
submit=request.getParameter("click");
System.out.println(submit);
if(submit.equals("add"))
result=n1+n2;
else
result=n1-n2;
response.setContentType("text/html");
PrintWriter
out=response.getWriter();
out.println("<HTML>");
out.println("<BODY
>");
out.println("<H3>
The results is:"+result+ "</H3>");
out.println("</BODY>");
out.println("</HTML>");
out.close();
}
}
Note: - In this web application we have to give same
request parameter name for both the submit buttons. Their captions must be
different. In the servlet, we have to call getParameter() on the request object
by supplying “submit” button’s request parameter name. It returns the caption
of the button, which, the end user clicked.
web.xml
<web-app>
<servlet>
<servlet-name>arithmetic</servlet-name>
<servlet-class>ComputeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>arithmetic</servlet-name>
<url-pattern>/compute</url-pattern>
</servlet-mapping>
</web-app>
Application Flow
- End-user
enters the URL for the numbers.html in the browser. Web server fetches the
web form to the client.
- End-user
enters 2 numbers into the web form and clicks on one of the 2 submit
buttons.
- Web server
receives the client request and dispatches it to the servlet engine.
- Servlet engine
picks up the public name of the servlet from the incoming request, looks
into the web.xml and dispatches the request to the ComputeServlet.
- In the
ComputeServlet, request object is used to capture the form data. I.e. 2
numbers. On which submit button end-user clicked also found, the result is
calculated and the response is given to the web server. I.e. to the
browser stream. Web server gives the response to the web client.
Performing database operations in servlets
While
a servlet is communicating with the databases the following observations are
made.
1. Driver
class, database URL, user name and password don’t hard code in the servlet. Get
them from the web.xml as initialization parameters. As a result our servlet
code will not change even when the database server, the driver or the
authentication information is changed.
- Almost all the
times make use of the PreparedStatement object to perform database
operations.
- Override zero
argument init method. In the init method, establish the database
connection and build the PreparedStatement object.
- If the web
form is submitted for retrieving data from the database, i.e. if the
client request is GET request, override the doGet method in the servlet.
- If the web
form is submitted for making changes in the database, i.e. if the client
request is POST request, override the doPost method in the servlet.
- Within the
doGet or doPost method perform database operations. I.e. executing the
PreparedStatement for submitting the SQL statement to the database.
- Close the
PreparedStatement and database connection in the destroy method.
- Implement
exception handling explicitly in init(), doGet() or doPost() and destroy()
methods. ClassNotFoundException and SQLException can’t be added to the
throws clause of these methods as it violates method overriding rule.
Supplying Initialization Parameters
In the web.xml the
following elements are used to supply initialization parameters to the
servlets.
<init-param>
<param-name>driver</param-name>
<param-value>sun.jdbc.odbc.JdbcOdbcDriver</param-value>
</init-param>
During servlet initialization phase the servlet engine
encapsulates these name value pairs of strings in the ServletConfig object and
passes them to the servlet. Within the servlet we retrieve the initialization
parameter value by calling getInitParameter method.
Q) Web application in which end-user enters the
employee number into the web form. Servlet sends the employee details in HTML
tabular format.
Directory structure
getapp
emp.html
WEB-INF
web.xml
classes
DatabaseServlet.class
After deployment
type the URL http://localhost:8080/getapp/emp.html
emp.html
<HTML>
<BODY
BGCOLOR="wheat">
<CENTER>
<FORM ACTION="./emp">
EMPNO<INPUT TYPE=text NAME="empno">
<INPUT TYPE=submit
VALUE="Send">
</FORM>
</CENTER>
</BODY>
</HTML>
DatabaseServlet.java
import java.io.*;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class DatabaseServlet extends HttpServlet
{
Connection
con;
public
void init() throws ServletException
{
String d=getInitParameter("driver");
String u=getInitParameter("url");
String us=getInitParameter("user");
String pwd=getInitParameter("pass");
try
{
Class.forName(d);
con=DriverManager.getConnection(u,us,pwd);
System.out.println("Connection is
established");
}
catch(ClassNotFoundException e)
{
System.out.println(e);
}
catch(SQLException e)
{
System.out.println("Unable
to establish the connection");
}
}//init()
public
void doGet(HttpServletRequest request,
HttpServletResponse response)throws ServletException,IOException
{
response.setContentType("text/html");
PrintWriter pw=response.getWriter();
try
{
pw.println("<HTML>");
pw.println("<BODY
BGCOLOR=wheat>");
pw.println("<CENTER>");
Statement
st=con.createStatement();
ResultSet
rs=st.executeQuery("SELECT * FROM
EMPLOYEE WHERE EMPNO="+request.getParameter("empno"));
ResultSetMetaData
metadata=rs.getMetaData();
int
count=metadata.getColumnCount();
if(rs.next())
{
pw.println("<H2>EMPLOYEE
DETAILS</H2>");
pw.println("<TABLE BORDER=1
CELLPADDING=3
CELLSPACING=0>");
pw.println("<TR>");
for(int i=1;i<=count;i++)
pw.println("<TH align=right
width=100>"+metadata.getColumnName(i)+"</TH>");
pw.println("</TR>");
pw.println("<TR>");
for(int i=1;i<=count;i++)
pw.println("<TD
align=right
width=100>"+rs.getString(i)+"</TD>");
pw.println("</TR>");
pw.println("</TABLE>");
}//if
else
pw.println("<H2> EMPLOYEE RECORD
NOT FOUND</H2>");
pw.println("</CENTER>");
pw.println("</BODY
>");
pw.println("</HTML>");
pw.close();
rs.close();
st.close();
}//try
catch(SQLException e)
{
System.out.println(e);
}
}//doGet()
public
void destroy()
{
if(con !=null)
{
try {con.close();}
catch(Exception e){}
System.out.println("Connection
closed");
}
}
}//class
web.xml
<web-app>
<servlet>
<servlet-name>jdbc</servlet-name>
<servlet-class>DatabaseServlet</servlet-class>
<init-param>
<param-name>driver</param-name>
<param-value>sun.jdbc.odbc.JdbcOdbcDriver</param-value>
</init-param>
<init-param>
<param-name>url</param-name>
<param-value>jdbc:odbc:student</param-value>
</init-param>
<init-param>
<param-name>user</param-name>
<param-value>scott</param-value>
</init-param>
<init-param>
<param-name>pass</param-name>
<param-value>tiger</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>jdbc</servlet-name>
<url-pattern>/emp</url-pattern>
</servlet-mapping>
</web-app>
Q) Web application to insert employee details into the
database.
Directory structure
Postapp
Emp.html
WEB-INF
Web.xml
Classes
PostServlet.class
After deployment http://localhost:8080/postapp/emp.html
is typed into the browser.
emp.html
<HTML>
<BODY
BGCOLOR=WHEAT>
<CENTER>
<H2>EMPLOYEE DETAILS</H2>
<FORM
ACTION="./pstmt" METHOD="POST" >
EMPNO <INPUT TYPE=TEXT NAME="empno"><BR><BR>
NAME <INPUT TYPE=TEXT NAME="name"><BR><BR>
SALARY <INPUT TYPE=TEXT
NAME="salary"><BR><BR>
<INPUT TYPE="SUBMIT" NAME="click"
VALUE="INSERT">
</FORM>
</CENTER>
</BODY>
</HTML>
After the end-user enters the details into the screen
and click on the insert button, same screen appears again to continue data
entry. From the servlet, the same web form is sent as response. As repetition
is involved in database operations, PreparedStatement is used in the servlet to
interact with the database.
PostServlet.java
import java.io.*;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class
PostServlet extends HttpServlet
{
Connection
con;
PreparedStatement
ps;
public
void init() throws ServletException
{
String d=getInitParameter("driver");
String u=getInitParameter("url");
String us=getInitParameter("user");
String pwd=getInitParameter("pass");
try
{
Class.forName(d);
con=DriverManager.getConnection(u,us,pwd);
System.out.println("Connection is
established");
ps=con.prepareStatement("INSERT INTO
EMPLOYEE VALUES(?,?,?)");
}
catch(Exception e)
{
System.out.println(e);
}
}//init()
public
void doPost(HttpServletRequest request, HttpServletResponse
response)throws ServletException,IOException
{
int
empno=Integer.parseInt(request.getParameter("empno"));
String
name=request.getParameter("name");
float
salary=Float.parseFloat(request.getParameter("salary"));
response.setContentType("text/html");
PrintWriter
out=response.getWriter();
try
{
ps.setInt(1,empno);
ps.setString(2,name);
ps.setFloat(3,salary);
ps.executeUpdate();
RequestDispatcher
rd=request.getRequestDispatcher("emp.html");
rd.include(request,response);
}//try
catch(SQLException
e)
{
System.out.println(e);
}
}//doPost()
public
void destroy()
{
if(ps
!=null)
{
try
{
ps.close();
}
catch(Exception e){}
}
if(con
!=null)
{
try
{
con.close();
}
catch(Exception
e){}
System.out.println("Connection
closed");
}
}//destroy
}//class
<web-app>
<servlet>
<servlet-name>insert</servlet-name>
<servlet-class>PostServlet</servlet-class>
<init-param>
<param-name>driver</param-name>
<param-value>oracle.jdbc.driver.OracleDriver</param-value>
</init-param>
<init-param>
<param-name>url</param-name>
<param-value>jdbc:oracle:thin:@localhost:1521:server</param-value>
</init-param>
<init-param>
<param-name>user</param-name>
<param-value>scott</param-value>
</init-param>
<init-param>
<param-name>pass</param-name>
<param-value>tiger</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>insert</servlet-name>
<url-pattern>/pstmt</url-pattern>
</servlet-mapping>
</web-app>
Observations to be made.
- In this
example, Oracle thin driver is used. We need to copy classes12.jar file
into the Tomcat 5.0\common\lib directory.
- RequestDispatcher object is used in order
to include emp.html into the servlet
response.
- As database
information is supplied from the web.xml, we can change the driver &
connection string without modifying the servlet source code.
- Even though
getInitParameter() is called on the servlet instance in the zero argument
init method, internally it is called on the ServletConfig object only.
Important Objects in Servlet
Programming
ServletContext:
Servlet engine
creates ServletContext object as soon as the web application is deployed. This
object is only one per web application. All servlets share this object.
ServletContext object is not directly available for servlets. To get its
reference we have to call the following method. ServletContext
sc=getServletContext();
Even though the above method is called on the servlet
instance, internally it is called on the ServletConfig object. I.e.
getServletContext method belongs to ServletConfig object.
ServletContext
object can be treated as shared informatory repository for application level
data. One servlet can store data into this object and another servlet of the
same application can access that data. A servlet uses this object for the
following purposes.
1.
To communicate with
the web container.
2.
To talk to other
servlets
3.
To share data (in
the form of attributes) with other servlets.
4.
To get application
level initialization parameters known as context parameters.
Whenever a servlet wants to know the web container
details in which it is deployed, it can call getServerInfo method on the
“sc”(ServletContext) object. To write any information into container log files
we call log method on “sc”. One servlet can store a data item into the
ServletContext object by calling setAttribute method. Another servlet can get
it by calling getAttribute method on the “sc” object. Whenever a servlet wants
to communicate with the other servlet, call getRequestDispatcher method on the
“sc” object. It produces RequestDispatcher object. Using RequestDispatcher
object one servlet can communicate with other servlets of the web application.
Initialization parameters are individual for each servlet. They are supplied
from web.xml. A servlet retrieves them by calling getInitParameter() on the
ServletConfig object. When we want to supply common init parameters for all the
servlets we use context parameters.
<context-param>
<param-name>anyname</param-name>
<param-value>anyvalue</param-value>
</context-param>
On the ServletContext we call getInitParameter() to
retrieve context parameters.
Q) Web application that explores the usage of
ServletContext object.
Directory structure
ServletContextApp
data.html
WEB-INF
web.xml
classes
StorageServlet.class
RetrieveServlet.class
After deploying the web application we type the
following URL in the browser.
We get the following screen.
When the end-user enters the details and clicks on the
submit button, the SourceServlet retrieves the user data and stores it into the
ServletContext object and gives the following response.
When the end-user clicks on the hyper link, the
TargetServlet retrieves data from the ServletContext object and send the same
to the client.
data.html
<HTML>
<BODY
BGCOLOR=pink>
<CENTER>
<H1>PERSONAL DETAILS</H1>
<FORM
ACTION="./store">
EMAIL ID<INPUT TYPE=text NAME="email"><BR>
PHONE <INPUT TYPE=text
NAME="phone"><BR><BR>
<INPUT TYPE=submit VALUE=SUBMITDETAILS>
</FORM>
</CENTER>
</BODY>
</HTML>
web.xml
<web-app>
<context-param>
<param-name>admin </param-name>
<param-value>admin@nit.com</param-value>
</context-param>
<servlet>
<servlet-name>storage</servlet-name>
<servlet-class>StorageServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>retrieval</servlet-name>
<servlet-class>RetrieveServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>storage</servlet-name>
<url-pattern>/store</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>retrieval</servlet-name>
<url-pattern>/retrieve</url-pattern>
</servlet-mapping>
</web-app>
StorageServlet.java
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class StorageServlet extends HttpServlet
{
public
void doGet(HttpServletRequest request,HttpServletResponse response)
throws IOException,ServletException
{
String
email=request.getParameter("email");
String
phone=request.getParameter("phone");
response.setContentType("text/html");
PrintWriter
pw=response.getWriter();
ServletContext
sc=getServletContext();
sc.setAttribute("mail",email);
sc.setAttribute("telephone",phone);
String
adminmail=sc.getInitParameter("admin");
pw.println("<HTML>");
pw.println("<BODY
BGCOLOR=wheat>");
pw.println("<H3>Websiteadminisavailable
at "+adminmail+"</H3>");
pw.println("<H2><AHREF=./retrieve>GET
YOUR DETAILS HERE
</A></H2>");
pw.println("</BODY>");
pw.println("</HTML>");
pw.close();
}
}
RetrieveServlet.java
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class RetrieveServlet extends HttpServlet
{
public
void doGet(HttpServletRequest request,HttpServletResponse response)
throws
IOException,ServletException
{
response.setContentType("text/html");
PrintWriter
pw=response.getWriter();
ServletContext
sc=getServletContext();
String
mail=(String)sc.getAttribute("mail");
String
phone=(String)sc.getAttribute("telephone");
String
adminmail=sc.getInitParameter("admin");
pw.println("<HTML>");
pw.println("<BODY
BGCOLOR=cyan>");
pw.println("<H2>
YOUR PERSONAL DETAILS</H2>");
pw.println("<H3>
EMAIL ID:"+mail+"</H2>");
pw.println("<H3>
TELEPHONE # :"+phone+"</H2>");
pw.println("<H3>Web
site admin is available at
"+adminmail+"</H3>");
pw.println("</BODY>");
pw.println("</HTML>");
pw.close();
}
}
RequestDispatcher object
RequestDispatcher object is used in the servlets to implement request
dispatching. A servlet receives the client request, does the processing
partially and hands over the request processing duty to another servlet. This
mechanism is known as request dispatching. Inter servlet communication is
implemented using RequestDispatcher object. In a servlet we can get
RequestDispatcher object reference in two ways.
- RequestDispatcher
rd=context.getRequestDispatcher(String absolutepath);
- RequestDispatcher
rd=request.getRequestDispatcher(String relativepath);
If we are
using the ServletContext object to get the RequestDispatcher, we have to give
absolute URL of the target resource. If we are using HttpServletRequest to get
the RequestDispatcher object, we give only relative url of the target resource.
Request dispatching can be implemented in two ways.
1.
forward mechanism
2.
include mechanism
In forward mechanism, a servlet receives the client
request, does the preliminary processing and request processing duty is
delegated to another servlet/jsp. The target resource is responsible to send
the response to the client. To implement forward mechanism the following code
has to be written in a servlet.
ServletContext
sc=getServletContext();
RequestDispatcher
rd=sc.getRequestDispatcher(“/targetservletpublicname”);
rd.forward(request,response);
In include mechanism; the content of a target resource
(a Servlet, a jsp, an html file) is included in the current servlet response.
In essence, this mechanism enables programmatic server side-includes. In this
mechanism the first servlet that receives the client request is responsible to
send the response to the client. To implement include mechanism we write the
following piece of code in the servlet.
ServletContext sc=getServletContext();
RequestDispatcher
rd=sc.getRequestDispatcher(“/targetservletpublicname”);
rd.forward(request,response);
In an object oriented system, objects communicate with message
passing. One object gets the reference of the other object and makes a method
call (sends a message) on the other object. This is how inter-object
communication occurs. In case of servlets, one servlet instance cannot get the
reference of other servlet instance. More over, one servlet cannot call the
life cycle methods of other servlets. Through RequestDispatcher object such
communication is made possible in servlets.
Q)
Web application on Request dispatching.
Directory Structure
dispatchapp
emp.html
caption.html
WEB-INF
web.xml
classes
GrossServlet.class
NetServlet.class
In this application end-user enters the basic pay of an
employee into the web form and expecting take home salary details. The first
servlet knows about allowances and therefore it calculates the gross salary. It
forwards the request to the second servlet to deal with deductions. While
forwarding, the first servlet stores the gross salary amount in the request
object so that the second servlet can retrieve it. It knows about deductions
and hence it calculates the take home salary. The second servlet is responsible
to send the response to the client. In this servlet, include mechanism also
implemented. It includes other html document output in its response. After
deployment of the web application we type the following URL in the browser
window.
When the end user enters the basic pay and clicks on the
submit button, the following response is sent to the client.
GrossServlet.java
import
javax.servlet.*;import javax.servlet.http.*;import java.io.*;
public
class GrossServlet extends HttpServlet
{
public void doGet(HttpServletRequest
request, HttpServletResponse response)
throws IOException,ServletException
{
float basic=Float.parseFloat(request.getParameter("basic"));
float da=0.5f*basic;
float hra=0.4f*basic;
float gross=basic+da+hra;
Float f=new Float(gross);
request.setAttribute("gross",f);
ServletContext sc=getServletContext();
RequestDispatcher rd=sc.getRequestDispatcher("/net");
rd.forward(request,response);
}
}
NetServlet.java
import
javax.servlet.*;import javax.servlet.http.*;import java.io.*;
public
class NetServlet extends HttpServlet
{ public void doGet(HttpServletRequest
request,HttpServletResponse response)
throws IOException,ServletException
{
response.setContentType("text/html");
PrintWriter out=response.getWriter();
Float gross=(Float)request.getAttribute("gross");
float
net=gross.floatValue()-2000-1000;
ServletContext sc=getServletContext();
RequestDispatcher
rd=sc.getRequestDispatcher(“/caption.html”);
rd.include(request,response);
out.println("<HTML>");
out.println("<BODY BGCOLOR=cyan>");
out.println("YOUR NET SALARY IS :"+net);
out.println("</BODY>");
out.println("</HTML>");
out.close();
}
}
web.xml
<web-app>
<servlet>
<servlet-name>source</servlet-name>
<servlet-class>GrossServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>target</servlet-name>
<servlet-class>NetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>source</servlet-name>
<url-pattern>/gross</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>target</servlet-name>
<url-pattern>/net</url-pattern>
</servlet-mapping>
</web-app>
caption.html
<HTML>
<BODY>
<MARQUEE><FONT
size=5 color=green>NO SUBSTITUTE FOR HARD WORK</FONT></MARQUEE>
</BODY>
</HTML>
Applying filters to servlets
A filter is a container-managed object that is
declaratively inserted within the request-response cycle of http client and
http server. A filter instance acts as an interceptor. It is a preprocessor of
the request before it reaches a servlet and a post processor of the response
leaving the servlet. A filter can
perform the following.
- Intercept a
servlet’s invocation before a servlet is called.
- Examine the
request before a servlet is called.
- Modify the
request headers and request data.
- Modify the
response headers and response data.
- Intercept a
servlet’s invocation after the servlet is called.
A filter object implements javax.servlet.Filter
interface. The interface provides 3 life cycle methods.
public void init(FilterConfig): - Servlet engine calls
this method only once after instantiating the filter. Initialization parameters
are encapsulated in the FilterConfig object. By calling getInitParameter method
in the FilterConfig object we can retrieve them.This method must complete
successfully before the filter is asked to do any filtering work.
public void
doFilter(ServletRequest,ServletResponse,FilterChain): - It is called by the
container each time a request/response pair is passed through the chain due to
a client request for a resource at the end of the chain. The FilterChain passed
into this method allows the filter to pass on the request and response to the
next entity in the chain.
public void destroy(): - Called by the servlet engine
to indicate to a filter that it is being taken out of service. This method
gives the filter an opportunity to clean up any resources that are being held.
For example, closing of the database connection.
Q) Web application in which, filters are applied to a
servlet.
In this example, two filters are applied to a servlet.
Applying more than one filter to a web resource is known as filter chaining.
The first filter authenticates the user before the request is forwarded to the
servlet. If authentication fails the filter itself sends the error page to the
client. If the user name and password are correct, the first filter switches
the control to the next filter. In this filter, the number of times the request
came to the servlet is captured ad the information is written to the container
log files.
Directory structure
filterchainingapp
login.html
error.html
WEB-INF
web.xml
classes
AuthenticationFilter.class
HitCounterFilter.class
WelcomeServlet.class
login.html
<HTML>
<BODY>
<FORM
action="./nit" METHOD="POST">
USERNAME<input type=text name=user><br>
PASSWORD<input type=password name=password><br>
<input
type=submit value=login>
</FORM>
</BODY>
</HTML>
error.html
<HTML>
<BODY>
<CENTER><H3>INVALID LOGIN OR
PASSWORD</H3></CENTER>
<FORM action="./nit" METHOD=POST>
USERNAME<input type=text name=user><br>
PASSWORD<input type=password
name=password><br>
<input type=submit value=login>
</FORM>
</BODY>
</HTML>
WelcomeServlet.java
import javax.servlet.*;import javax.servlet.http.*;
import java.io.*;
public class WelcomeServlet extends HttpServlet
{
public void
doPost(HttpServletRequest request,HttpServletResponse response)
throws IOException,ServletException
{
response.setContentType("text/html");
PrintWriter pw=response.getWriter();
pw.println("WELCOME TO OUR
WEBSITE");
pw.close();
}
}
AuthenticationFilter.java
import javax.servlet.*;import java.io.*;import
java.sql.*;
public class AuthenticationFilter implements Filter
{
ServletContext
sc;
Connection
con;
public
void init(FilterConfig f) throws
ServletException
{
System.out.println("Filter
initailized");
String
d=f.getInitParameter("driver");
String
url=f.getInitParameter("url");
String
usr=f.getInitParameter("user");
String
pwd=f.getInitParameter("pass");
try
{
Class.forName(d);
con=DriverManager.getConnection(url,usr,pwd);
System.out.println("connection
established");
}
catch(Exception
e)
{
e.printStackTrace();
}
sc=f.getServletContext();
}
public void doFilter(ServletRequest request,
ServletResponse
response, FilterChain chain)
throws
IOException,ServletException
{
Statement
st=null;
ResultSet
rs=null;
String
user=request.getParameter("user");
String
pwd=request.getParameter("password");
try
{
st=con.createStatement();
String sql="SELECT * FROM OURUSERS WHERE usr='"+user+"'
and
password='"+pwd+"'";
rs=st.executeQuery(sql);
if(rs.next())
chain.doFilter(request,response);
else
sc.getRequestDispatcher("/error.html").forward(request,response);
}
catch(Exception
e)
{
e.printStackTrace();
}
finally
{
try
{
if(rs !=null)
rs.close();
if(st !=null)
st.close();
}
catch(Exception e) { e.printStackTrace(); }
}
}
public
void destroy()
{
try
{
if(con !=null)
con.close();
}
catch(Exception e) { e.printStackTrace(); }
}
}
HitCounterFilter.java
import javax.servlet.*;
import java.io.*;
public class HitCounterFilter implements Filter
{
ServletContext
sc;
int
count;
public
void init(FilterConfig f) throws
ServletException
{
sc=f.getServletContext();
}
public
void doFilter(ServletRequest request,ServletResponse
response,FilterChain chain)
throws
IOException,ServletException
{
chain.doFilter(request,response);
count++;
sc.log("Number
of times request came to LoginServlet is "+count);
}
public
void destroy(){}
}
web.xml
<web-app>
<filter>
<filter-name>auth</filter-name>
<filter-class>AuthenticationFilter</filter-class>
<init-param>
<param-name>driver</param-name>
<param-value>oracle.jdbc.driver.OracleDriver</param-value>
</init-param>
<init-param>
<param-name>url</param-name>
<param-value>jdbc:oracle:thin:@localhost:1521:server</param-value>
</init-param>
<init-param>
<param-name>user</param-name>
<param-value>scott</param-value>
</init-param>
<init-param>
<param-name>pass</param-name>
<param-value>tiger</param-value>
</init-param>
</filter>
<filter>
<filter-name>hitcount</filter-name>
<filter-class>HitCounterFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>auth</filter-name>
<url-pattern>/nit</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>hitcount</filter-name>
<url-pattern>/nit</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>Login</servlet-name>
<servlet-class>WelcomeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Login</servlet-name>
<url-pattern>/nit</url-pattern>
</servlet-mapping>
</web-app>
Session Tracking
Http is a stateless protocol. A
web client opens a connection with the http server and requests some
resource. The server responds with the
requested resource and closes the connection with client. After closing the connection, the http server
does not remember any information about the client. The server considers the next request from
the same client as a fresh request, with no relation to the previous
request. This is what the stateless
nature of the Http protocol.
In enterprise web application it is mandatory that client and its
associated data must be tracked at server side across multiple requests. There are four approaches to achieve this.
·
Hidden from fields
·
Cookies
·
Session tracking with SERVLE API
·
URL rewriting
Note: For Hidden form fields mechanism there is no SERVLET API support
available.
Hidden form
fields:
- A hidden field is similar to an ordinary input field
in HTML. The only difference is that the hidden field doesn’t have an
associated user-interface element. When
the form that contains these hidden fields is submitted, the values of these
fields are sent with the request. On the
server side, these values are received as request parameters. This mechanism works only when form is
submitted, not when you click the hyperlink.
The key point is that client selected data travels invisibly from client
to server and server to client in this mechanism. That is how state is managed across multiple
requests. In J2EE environment this
mechanism is not so widely used, as there is no SERVLETS API support available.
Cookies Mechanism
This is a widely used mechanism for both state management and session
management. A cookie is a simple place
of information stored on the client, on behalf of the server. This information is returned to the server
with every request, in addition to the requested document, if may choose to
return some state information to the browser.
This information includes a URL
range within which the information should be returned to the server. The URL range comprises the domain name and
some path within the domain. Whenever
the browser requests a resource. It
cheeks the URL against the URL range of all available cookies. If a match is found, the cookie is also
returned with the request. This helps
the server overcome the stateless nature of the Http protocol.
Using the cookie mechanism in a Servlet involves the following steps.
Step1: - creating the instance of javax.Servlet.http.Cookie class.
Cookie c=new Cooke (“user”, “rama”);
Step 2: - Making the cookie persistent
c.setMaxAge
(3600);
Step 3: - Writing the cookie to the response header.
response.addCookei(c);
Step 4: To retrieve the cookie we call the following method.
Cookie c[] =
request.getCookies();
List of
important methods in cookie class:
·
public String getName():- Returns
the name of the cookie.
·
public String getvalue():- Returns
the value of the cookie.
·
public void setMaxAge(int expiry):-
Sets the maximum age of the cookie in seconds.
A positive value indicates that the cookie will expire after that many
seconds have passed, note that the value is the maximum age when the cookie
will expire, not the cookie’s current age.
A negative value means that the cookie is not stored persistently and
will be deleted when the web browser exits.
A zero value causes the cookie to be deleted.
·
public void setDomain(String
pattern):- Specifies the domain within which this cookies should be presented.
By default, cookies are only returned to the server that sent them.
Q) Web Application cookies implementation
Directory Structure
Cookieapp
Cookieexample.html
WEB-INF
web.xml
classes
CreateCookie.class
CheckCookie.class
After the web application is deployed, the following URL has to be
typed into browser.
http://localhost:
8080/cookieapp/cookieexample.html
When the end-user enters the name and clicks on the
button, the first servlet retrieves the name, convert it into a cookie, and
send to the client.When the end-user clicks on the hyper link ,the cookie is
sent to the web server again.
Cookieexample.html
<HTML>
<BODY BGCOLOR="cyan">
<CENTER>
<H2> WELCOME TO SHOPPING MALL
</H2>
<FORM ACTION="./create"
METHOD="post">
<B>UserName</B>
<INPUT TYPE=text NAME="user"><br><br>
<INPUT TYPE="submit"
VALUE="WELCOME"><br><br>
</FORM>
</CENTER>
</BODY>
</HTML>
CreateCookie.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class CreateCookie extends
HttpServlet
{
public
void doPost(HttpServletRequest req,HttpServletResponse res)
throws
ServletException,IOException
{
String
name=req.getParameter("user");
res.setContentType("text/html");
PrintWriter
pw=res.getWriter();
Cookie
c=new Cookie("user",name);
res.addCookie(c);
pw.println("<HTML>");
pw.println("
<BODY BGCOLOR=wheat><CENTER>");
pw.println("<H2><A
HREF=./check>SHOPPING GOES HERE</A></H2>");
pw.println("</CENTER></BODY><HTML>");
pw.close();
}
}
CheckCookie.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class
CheckCookie extends HttpServlet
{
public void
doGet(HttpServletRequest req, HttpServletResponse res)
ServletException,IOException
{
res.setContentType("text/html");
PrintWriter
pw=res.getWriter();
Cookie
c[]=req.getCookies();
pw.println("<HTML><BODY
BGCOLOR=wheat><H2>");
pw.println("
Hai "+c[0].getValue()+" ! hope enjoying
shopping here </H2>");
pw.println(“</BODY>”);
pw.println(“</HTML>”);
pw.close();
}//method
}//class
web.xml
<web-app>
<servlet>
<servlet-name>create</servlet-name>
<servlet-class>CreateCookie</servlet-class>
</servlet>
<servlet>
<servlet-name>check</servlet-name>
<servlet-class>CheckCookie</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>create</servlet-name>
<url-pattern>/create</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>check</servlet-name>
<url-pattern>/check</url-pattern>
</servlet-mapping>
</web-app>
Session Tracking using HttpSession
Session tracking is the ability of the web container to
recognize a client uniquely in a series of interactions and also able to
associate each request with a particular client. HttpSession object represents
the association. The web container maintains this object for the duration of
the client session or a configurable time period. Since many clients interact
with the container, the container maintains individual HttpSession objects for
each client. By using HttpSession object methods we can associate the client
state also with the session object. We create the HttpSession object as
follows.
HttpSession
s=request.getSession();
The above method returns the reference to the container
created object that implements the HttpSession interface. If there is no
session associated with the current request, the above method creates one. If
already a session is associated with the client, it gives the reference to the
existing session object.
Important methods of HttpSession
Methods for session
lifetime: -
·
public long
getCreationTime(): - Returns the time that the session was created, in
milliseconds since Jan 1, 1970 00.00 hrs.
·
public String
getId(): - Returns a String containing a unique identifier assigned to this
session.
·
Public long
getLastAccessedTime(): - Returns the time that the session was last accessed by
the client, in milliseconds since Jan 1, 1970 00.00 hrs. This method is used to
determine the period of inactivity between two consecutive client requests.
·
public int
getMaxInactiveInterval(): - Returns the length of the time in seconds that the
session will remain active between requests before expiring.
·
public void
setMaxInactiveInterval(int seconds): -
This method sets the length of time in seconds that the session will
remain active between requests before expiring. The web container makes sure
that the session is automatically invalidated after expiry of this interval.
·
public Boolean
isNew(): - Returns true if the client does not yet know about the session. A
client is considered to join a session when it returns session tracking
information previously sent by the server.
·
public void
invalidate():- invalidates the session and unbinds any data associated with it.
Methods for session associating state with session: -
- public void
setAttribute(String name,Object value): - stores a value in the session
object with some name.
- public void
getAttribute(String name): - Returns the object bound with the specified
name in this session, or null if no object is bound under the name.
- public void
removeAttribute(String name): -
Removes the object bound to the session.
- public
Enumeration getAttributeNames(): -
Returns an Enumeration of String objects bound to the session.
These strings are names given to the objects bound to the session.
URL rewriting
When we are implementing session tracking using
HttpSession, web container implicitly uses cookies mechanism to exchange the
session id between the client and the server. If cookies are disabled in the
client, session tracking fails. To overcome this problem we make use of URL
rewriting. Appending the session id to
the URL is known as URL rewriting. In order for this mechanism to work, all the
URLs in the page should be encoded using encodeURL() method of the
HttpServletResponse. This method encodes
the specified URL by including the session id in it, or, if encoding is not
needed, returns the URL unchanged. For robust session tracking, all URLs
emitted by the servlet should run through this method.
Q) Web application to implement URL rewriting.
Directory structure
rewriteapp
user.html
WEB-INF
web.xml
classes
SourceServlet.class
TargetServlet.class
After deployment of the web application, type the
following URL in the browser.
When the end-user clicks on the submit button, the source
servlet receives the name and stores it in the session object. It sends a
hyperlink to the client as response. If we keep the mouse pointer on the hyper
link, we can observe the appended session id in the status bar. This is the
effect of URL rewriting. When the end-user clicks on the hyper link, the second
servlet receives the request. The container picks up the session id from the
request line and gives the existing session object. The servlet retrieves the
name from the session object and sends the output to the client.
user.html
<HTML>
<BODY BGCOLOR="cyan">
<CENTER>
<FORM
ACTION="./source" >
<B>UserName</B>
<INPUT TYPE=text NAME="user"><br><br>
<INPUT
TYPE="submit" VALUE="WELCOME"><br><br>
</FORM>
</CENTER>
</BODY>
</HTML>
SourceServlet.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class
SourceServlet extends HttpServlet
{
public
void doGet(HttpServletRequest req, HttpServletResponse
res)
throws
ServletException,IOException
{
String name=req.getParameter("user");
res.setContentType("text/html");
PrintWriter
pw=res.getWriter();
HttpSession
s=req.getSession();
s.setAttribute("usr",name);
pw.println("<HTML>");
pw.println("
<BODY BGCOLOR=wheat><CENTER>");
pw.println("<H2><A
HREF="+res.encodeURL("./target")+">GET USER
NAME
HERE</A></H2>");
pw.println("</CENTER></BODY><HTML>");
pw.close();
}
}
TargetServlet.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class TargetServlet
extends HttpServlet
{
public
void doGet(HttpServletRequest req, HttpServletResponse
res)
throws
ServletException,IOException
{
res.setContentType("text/html");
PrintWriter
pw=res.getWriter();
HttpSession
s=req.getSession();
String
user=(String)s.getAttribute("usr");
pw.println("<HTML>”
pw.println(“<BODY BGCOLOR=wheat>”);
pw.println("
Hai "+user+" ! hope
enjoying shopping here
</H2>");
pw.println(“</BODY>”);
pw.println(“</HTML>”);
pw.close();
}
}
web.xml
<web-app>
<servlet>
<servlet-name>one</servlet-name>
<servlet-class>SourceServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>two</servlet-name>
<servlet-class>TargetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>one</servlet-name>
<url-pattern>/source</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>two</servlet-name>
<url-pattern>/target</url-pattern>
</servlet-mapping>
</web-app>
Event Listeners in Servlets
Listeners are the way to receive notifications when
important events occur in a web application. To receive notification of an
event, we need to write a class that implements the corresponding listener
interface. The servlet engine then calls the appropriate methods of the
listener classes when event occurs. Some important Listener interfaces in the
SERVLET API are
·
ServletContextListener
·
ServletContextAttributeListener
·
ServletRequestListener
·
ServletRequestAtributeListener
·
HttpSessionListener
·
HttpSessionAttributeListener
ServletContextListener: - This interface allows us to know when a
ServletContext is initialized or destroyed. It has 2 methods.
1. public
void contextDestroyed(ServletContextEvent sce): - This method is called soon
after the ServletContext is destroyed. I.e. when the web application is
undeployed.
- public void
contextInitialized(ServletContextEvent sce): -Servlet engine calls
this method as soon as the ServletContext object is initialized.
ServletContextAttributeListener: - This interface is used to receive notifications
about the changes to the attribute list of a ServletContext. It has 3 methods.
- public void
attributeAdded(ServletContextAttributeEvent scae): -Servlet engine calls
this method as soon an attribute is added to the ServletContext.
- public void
attributeRemoved(ServletContextAttributeEvent scae): - It is called when
an existing attribute is removed from the ServletContext.
- public void
attributeReplaced(ServletContextAttributeEvent scae): -Servlet engine
calls this method when an attribute of the ServletContext is replaced.
ServletRequestListener: - Implementations of
this interface receive notifications about changes to the servlet request of
the web application they are part of. To receive notification events, the
implementation class must be configured in the deployment descriptor for the
web application. It has 2 methods.
- public void
requestDestoryed(ServletRequestEvent sre): - Notification that the servlet request
is about to go out of scope.
- public void
requestInitialized(ServletRequestEvent sre): - Notification that the servlet request
is about to go into scope.
ServletRequestAttributeListener: -Implementations of this interface receives
notifications of changes to the attribute list on the servlet request of a web
application. To receive notification events, the implementation class must be
configured in the deployment descriptor for the web application. It has the following
methods.
1. public void attributeAdded(ServletRequestAttributeEvent srae)
Notification that a new attribute was added to the
servlet request. Called after the attribute is added.
2. public void attributeRemoved(ServletRequestAttributeEvent srae)
Notification that an existing attribute has been
removed from the servlet request. Called after the attribute is removed.
3. public void attributeReplaced(ServletRequestAttributeEvent srae)
Notification that an attribute on the servlet request
has been replaced. Called after the attribute is replaced.
HttpSessionListener: - Implementations of this interface are notified of
changes to the list of active sessions in a web application. To receive
notification events, the implementation class must be configured in the deployment
descriptor for the web application. This interface has the following methods.
1. public void sessionCreated(HttpSessionEvent se)
Notification that a session was created.
2. public void sessionDestroyed(HttpSessionEvent se)
Notification that a session is about to be invalidated.
HttpSessionAttributeListener:
- This listener interface can be implemented in order to get
notifications of changes to the attribute lists of sessions within this web
application. 1. attributeAdded(HttpSessionBindingEvent se) :- Called after the attribute is added.
2. attributeRemoved(HttpSessionBindingEvent se): - Called after the attribute is removed.attributeReplaced(HttpSessionBindingEvent se): - Called after the attribute is replaced.
good subject delivery