SERVLETS Class Notes

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 20

SERVLETS

Java Servlets is a web technology for Java. It was the first web technology for Java and many
new web technologies have arrived since. Still, Java Servlets are very useful, both to know, and
for certain use cases.

Java Servlets are part of the Java Enterprise Edition (Java EE). You will need to run your Java
Servlets inside a Servlet compatible "Servlet Container" (e.g. web server) in order for them to
work.

Servlet Life Cycle

A servlet follows a certain life cycle. The servlet life cycle is managed by the servlet container.
The life cycle contains the following steps:

1. Load Servlet Class.


2. Create Instance of Servlet.
3. Call the servlets init() method.
4. Call the servlets service() method.
5. Call the servlets destroy() method.

Step 1, 2 and 3 are executed only once, when the servlet is initially loaded. By default the servlet
is not loaded until the first request is received for it. You can force the container to load the
servlet when the container starts up though. See web.xml Servlet Configuration for more details
about that.

Step 4 is executed multiple times - once for every HTTP request to the servlet.
Step 5 is executed when the servlet container unloads the servlet.
Each step is described in more detail below:
The Java Servlet life cycle

Load Servlet Class


Before a servlet can be invoked the servlet container must first load its class definition. This is
done just like any other class is loaded.

Create Instance of Servlet


When the servlet class is loaded, the servlet container creates an instance of the servlet.

Typically, only a single instance of the servlet is created, and concurrent requests to the servlet
are executed on the same servlet instance. This is really up to the servlet container to decide,
though. But typically, there is just one instance.
Call the Servlets init() Method
When a servlet instance is created, its init() method is invoked. The init() method allows a
servlet to initialize itself before the first request is processed.

You can specify init parameters to the servlet in the web.xml file. See web.xml Servlet
Configuration for more details.

Call the Servlets service() Method


For every request received to the servlet, the servlets service() method is called. For
HttpServlet subclasses, one of the doGet(), doPost() etc. methods are typically called.

As long as the servlet is active in the servlet container, the service() method can be called.
Thus, this step in the life cycle can be executed multiple times.

Call the Servlets destroy() Method


When a servlet is unloaded by the servlet container, its destroy() method is called. This step is
only executed once, since a servlet is only unloaded once.

A servlet is unloaded by the container if the container shuts down, or if the container reloads the
whole web application at runtime.

Java Servlet Example

A Java Servlet is just an ordinary Java class which implements the interface

javax.servlet.Servlet;

The easiest way to implement this interface is to extend either the class GenericServlet or
HttpServlet.

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;

public class SimpleServlet extends GenericServlet {


public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {

// do something in here
}
}

When an HTTP request arrives at the web server, targeted for your Servlet, the web server calls
your Servlet's service() method.

The service() method then reads the request, and generates a response which is sent back to
the client (e.g. a browser).

Here is an example service() implementation:

public void service(ServletRequest request, ServletResponse response)


throws ServletException, IOException {

String yesOrNoParam = request.getParameter("param");

if("yes".equals(yesOrNoParam) ){

response.getWriter().write(
"<html><body>You said yes!</body></html>");
}

if("no".equals(yesOrNoParam) ){

response.getWriter().write(
"<html><body>You said no!</body></html>");
}
}

This service() method first reads the request parameter "param". Then it checks if the param is
equal to the text "yes" or "no", and writes an HTML response back to the browser.

HttpServlet

The javax.servlet.http.HttpServlet class is a slightly more advanced base class than the
GenericServlet shown in the Simple Servlet example.

The HttpServlet class reads the HTTP request, and determines if the request is an HTTP GET,
POST, PUT, DELETE, HEAD etc. and calls one the corresponding method.

To respond to e.g. HTTP GET requests only, you will extend the HttpServlet class, and
override the doGet() method only. Here is an example:

public class SimpleHttpServlet extends HttpServlet {


protected void doGet( HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {

response.getWriter().write("<html><body>GET response</body></html>");
}
}

The HttpServlet class has methods you can override for each HTTP method (GET, POST etc.).
Here is a list of the methods you can override:

 doGet()
 doPost()
 doHead()
 doPut()
 doDelete()
 doOptions()
 doTrace()

Most often you just want to respond to either HTTP GET or POST requests, so you just override
these two methods.

If you want to handle both GET and POST request from a given servlet, you can override both
methods, and have one call the other. Here is how:

public class SimpleHttpServlet extends HttpServlet {

protected void doGet( HttpServletRequest request,


HttpServletResponse response)
throws ServletException, IOException {

doPost(request, response);
}

protected void doPost( HttpServletRequest request,


HttpServletResponse response)
throws ServletException, IOException {

response.getWriter().write("GET/POST response");
}
}

I would recommend you to use the HttpServlet instead of the GenericServlet whenever
possible. HttpServlet is easier to work with, and has more convenience methods than
GenericServlet.
HttpRequest

The HttpServlet class request processing methods take two parameters.

1. javax.servlet.http.HttpRequest
2. javax.servlet.http.HttpResponse

For instance, here is the signature of the HttpServlet.doGet() method:

protected void doGet(


HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {

In this text I will look at the HttpRequest object.

The purpose of the HttpRequest object is to represent the HTTP request a browser sends to your
web application. Thus, anything the browser may send, is accessible via the HttpRequest.

The HttpRequest object has a lot of methods, so I will just cover the most commonly used here.
The rest you can read about in the JavaDoc, if you are interested. The parts I will cover are:

1. Parameters
2. Headers
3. InputStream
4. Session
5. ServletContext

Parameters
The request parameters are parameters that are sent from the browser along with the request.
Request parameters are typically sent as part of the URL (in the "query string"), or as part of the
body of an HTTP request. For instance:

http://jenkov.com/somePage.html?param1=hello¶m2=world

Notice the "query string" part of the URL: ?param1=hello¶m2=world This part contains two
parameters with parameter values:

param1=hello
param2=world

You can access these parameters from the HttpRequest object like this:
protected void doGet(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {

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


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

You would use the same code, if the request parameters were sent in the body part of the HTTP
request. If no parameter exists with the given name, null is returned.

In general, if the browser sends an HTTP GET request, the parameters are included in the query
string in the URL. If the browser sends an HTTP POST request, the parameters are included in
the body part of the HTTP request.

Headers
The request headers are name, value pairs sent by the browser along with the HTTP request. The
request headers contain information about e.g. what browser software is being used, what file
types the browser is capable of receiving etc. In short, at lot of meta data around the HTTP
request.

You can access the request headers from the HttpRequest object like this:

String contentLength = request.getHeader("Content-Length");

This example reads the Content-Length header sent by the browser.

The Content-Length header contains the number of bytes sent in the HTTP request body, in
case the browser sends an HTTP POST request. If the browser sends an HTTP GET request, the
Content-Length header is not used, and the above code will return null.

In general, If no header exists with the name passed to getHeader(), null is returned.

InputStream
If the browser sends an HTTP POST request, request parameters and other potential data is sent
to the server in the HTTP request body. It doesn't have to be request parameters that is sent in the
HTTP request body. It could be pretty much any data, like a file or a SOAP request (web service
request).
To give you access to the request body of an HTTP POST request, you can obtain an
InputStream pointing to the HTTP request body. Here is how it is done:

InputStream requestBodyInput = request.getInputStream();

NOTE: You will have to call this method before calling any getParameter() method, because
calling the getParameter() method on an HTTP POST request will cause the servlet engine to
parse the HTTP request body for parameters. Once parsed, you cannot access the body as a raw
stream of bytes anymore.

Session
It is possible to obtain the session object from the HttpRequest object too.

The session object can hold information about a given user, between requests. So, if you set an
object into the session object during one request, it will be available for you to read during any
subsequent requests within the same session time scope.

Here is how you access the session object from the HttpRequest object:

HttpSession session = request.getSession();

ServletContext
You can access the ServletContext object from the HttpRequest object too. The
ServletContext contains meta information about the web application. For instance, you can
access context parameters set in the web.xml file, you can forward the request to other servlets,
and you can store application wide parameters in the ServletContext too.

Here is how you access the ServletContext object from the HttpRequest object:

ServletContext context = request.getSession().getServletContext();

As you can see, you have to first get the session object, to get access to the ServletContext
object.

HttpResponse

The HttpServlet class request processing methods take two parameters.

1. javax.servlet.http.HttpRequest
2. javax.servlet.http.HttpResponse
For instance, here is the signature of the HttpServlet.doGet() method:

protected void doGet(


HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {

In this text I will look at the HttpResponse object.

The purpose of the HttpResponse object is to represent the HTTP response your web application
sends back to the browser, in response to the HTTP request the browser send to your web
application.

The HttpResponse object has a lot of methods, so I will just cover the most commonly used
here. The rest you can read about in the JavaDoc, if you are interested. The parts I will cover are:

1. Writing HTML
2. Headers
3. Content-Type
4. Writing Text
5. Content-Length
6. Writing Binary Data
7. Redirecting to a Different URL

Writing HTML
To send HTML back to the browser, you have to obtain the a PrintWriter from the
HttpResponse object. Here is how:

PrintWriter writer = response.getWriter();

writer.write("<html><body>GET/POST response</body></html>");

Headers
Just like the request object, the HttpRequest can contain HTTP headers. Headers must be set
before any data is written to the response. You set a header on the response object like this:

response.setHeader("Header-Name", "Header Value");

As you can see, a response header is a name, value pair.


Content-Type
The Content-Type header is a response header that tells the browser the type of the content you
are sending back to it. For instance, the content type for HTML is text/html. Similarly, if what
you send back to the browser is plain text, you use the content type text/plain.

Here is how you set the Content-Type header on the HttpResponse object:

response.setHeader("Content-Type", "text/html");

Writing Text
You can write text back to the browser instead of HTML, like this:

response.setHeader("Content-Type", "text/plain");

PrintWriter writer = response.getWriter();


writer.write("This is just plain text");

First the Content-Type header is set to text/plain. Then a plain text string is written to the
writer obtained from the response object.

Content-Length
The Content-Length header tells the browser how many bytes your servlet is sending back. If
you are sending binary data back you need to set the content length header. Here is how:

response.setHeader("Content-Length", "31642");

Writing Binary Data


You can also write binary data back to the browser instead of text. For instance, you can send an
image back, a PDF file or a Flash file or something like that.

Again, you will first have to set the Content-Type header to the type matching the data you are
sending back. For instance, the content type for a PNG image is image/png.

You can search for "mime types" in your favourite search engine to find a list of mime types
(content types), so you can find the mime type for the content you are sending back.
In order to write binary data back to the browser you cannot use the Writer obtained from
response.getWriter(). Afterall, Writer's are intended for text.

Instead you have to use the OutputStream obtained from the response.getOutputStream()
method. Here is how:

OutputStream outputStream = response.getOutputStream();

outputStream.write(...);

Redirecting to a Different URL


You can redirect the browser to a different URL from your servlet. You cannot send any data
back to the browser when redirecting. Here is how you redirect:

response.sendRedirect("http://jenkov.com");

RequestDispatcher

The RequestDispatcher class enables your servlet to "call" another servlet from inside another
servlet. The other servlet is called as if an HTTP request was sent to it by a browser.

You can obtain a RequestDispatcher from the HttpServletRequest object, like this:

protected void doPost(HttpServletRequest request,


HttpServletResponse response)
throws ServletException, IOException {

RequestDispatcher requestDispatcher =
request.getRequestDispatcher("/anotherURL.simple");
}

The above code obtains a RequestDispatcher targeted at whatever Servlet (or JSP) that is
mapped to the URL /anotherUrl.simple.

You can call the RequestDispatcher using either its include() or forward() method:

requestDispatcher.forward(request, response);

requestDispatcher.include(request, response);

By calling either the include() or forward() method the servlet container activates whatever
Servlet is mapped to the URL the RequestDispatcher.
The activated servlet has access to the same request as the servlet calling it, and will write to the
same response as your current servlet. That way you can merge the output of servlets into a
single repsonse.

There is a little difference between calling the forward() and include() method.

The forward() method intended for use in forwarding the request, meaning after the response
of the calling servlet has been committed. You cannot merge response output using this method.

The include() method merges the response written by the calling servlet, and the activated
servlet. This way you can achieve "server side includes" using the include().

HttpSession

The HttpSession object represents a user session. A user session contains information about the
user across multiple HTTP requests.

When a user enters your site for the first time, the user is given a unique ID to identify his
session by. This ID is typically stored in a cookie or in a request parameter.

Here is how you access the session object:

protected void doPost(HttpServletRequest request,


HttpServletResponse response)
throws ServletException, IOException {

HttpSession session = request.getSession();


}

You can store values in the session object, and retrieve them later. First, let's see how you can
store values in the session object:

session.setAttribute("userName", "theUserName");

This code sets an attribute named "userName", with the value "theUserName".

To read the value again, you do this:

String userName = (String) session.getAttribute("userName");

Values stored in the session object are stored in the memory of the servlet container.

Sessions and Clusters


If you have an architecture with 2 web servers in a cluster, keep in mind that values stored in the
session object of one server, may not be available in the session object on the other server. So, if
a user's requests are divided evenly between the two servers, sometimes session values may be
missing.

The solution to this problem would be one of:

1. Do not use session attributes.


2. Use a session database, into which session attributes are written, and from which it is
read.
3. Use sticky session, where a user is always sent to the same server, throughout the whole
session.

ServletContext

The ServletContext is an object that contains meta informaton about your web application.
You can access it via the HttpRequest object, like this:

ServletContext context = request.getSession().getServletContext();

Context Attributes
Just like in the session object you can store attributes in the servlet context. Here is how:

context.setAttribute("someValue", "aValue");

You can access the attributes again like this:

Object attribute = context.getAttribute("someValue");

The attributes stored in the ServletContext are available to all servlets in your application, and
between requests and sessions. That means, that the attributes are available to all visitors of the
web application. Session attributes are just available to a single user.

The ServletContext attributes are still stored in the memory of the servlet container. That
means that the same problems exists as does with the session attributes, in server clusters.
Web.xml Servlet Configuration

For a Java servlet to be accessible from a browser, you must tell the servlet container what
servlets to deploy, and what URL's to map the servlets to. This is done in the web.xml file of
your Java web application.

If you are not familiar with the directory layout and contents of a Java web application,: Java
Web Application Directory Layout

Here is a list of the topics covered in this text about the web.xml servlet configuration:

1. Configuring and Mapping a Servlet


2. Servlet Init Parameters
3. Servlet Load-on-Startup
4. Context Parameters

Configuring and Mapping a Servlet


To configure a servlet in the web.xml file, you write this:

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

<servlet>
<servlet-name>controlServlet</servlet-name>
<servlet-class>com.jenkov.butterfly.ControlServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>controlServlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
</web-app>

First you configure the servlet. This is done using the <servlet> element. Here you give the
servlet a name, and writes the class name of the servlet.

Second, you map the servlet to a URL or URL pattern. This is done in the <servlet-mapping>
element. In the above example, all URL's ending in .html are sent to the servlet.

Other possible servlet URL mappings are:


/myServlet

/myServlet.do

/myServlet*

The * is a wild card, meaning any text. As you can see, you can either map a servlet to a single,
specific URL, or to a pattern of URL's, using a wild card (*). What you will use depends on what
the servlet does.

Servlet Init Parameters


You can pass parameters to a servlet from the web.xml file. The init parameters of a servlet can
only be accessed by that servlet. Here is how you configure them in the web.xml file:

<servlet>
<servlet-name>controlServlet</servlet-name>
<servlet-class>com.jenkov.butterfly.ControlServlet</servlet-class>

<init-param>
<param-name>myParam</param-name>
<param-value>paramValue</param-value>
</init-param>
</servlet>

Here is how you read the init parameters from inside your servlet - in the servlets init()
method:

public class SimpleServlet extends GenericServlet {

protected String myParam = null;

public void init(ServletConfig servletConfig) throws ServletException{


this.myParam = servletConfig.getInitParameter("myParam");
}

public void service(ServletRequest request, ServletResponse response)


throws ServletException, IOException {

response.getWriter().write("<html><body>myParam = " +
this.myParam + "</body></html>");
}
}

A servlets init() method is called when the servlet container loads the servlet for the first time.
No one can access the servlet until the servlet has been loaded, and the init() method has been
called successfully.
Servlet Load-on-Startup
The <servlet> element has a subelement called <load-on-startup> which you can use to
control when the servlet container should load the servlet. If you do not specify a <load-on-
startup> element, the servlet container will typically load your servlet when the first request
arrives for it.

By setting a <load-on-startup> element, you can tell the servlet container to load the servlet as
soon as the servlet container starts. Remember, the servlets init() method is called when the
servlet is loaded.

Here is an example <load-on-startup> configuration:

<servlet>
<servlet-name>controlServlet</servlet-name>
<servlet-class>com.jenkov.webui.ControlServlet</servlet-class>
<init-param><param-name>container.script.static</param-name>
<param-value>/WEB-INF/container.script</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

The number inside the <load-on-startup>1</load-on-startup> element tells the servlet


container in what sequence the servlets should be loaded. The lower numbers are loaded first. If
the value is negative, or unspecified, the servlet container can load the servlet at any time.

Context Parameters
You can also set some context parameters which can be read from all servlets in your
application. Here is how you configure a context parameter:

<context-param>
<param-name>myParam</param-name>
<param-value>the value</param-value>
</context-param>

Here is how you access the parameter from inside an HttpServlet subclass:

String myContextParam =
request.getSession()
.getServletContext()
.getInitParameter("myParam");
The WEB-INF Directory

The WEB-INF directory is located just below the web app root directory. This directory is A Meta
Information Directory. Files stored in here are not supposed to be accessible from a browser
(although your web app can access them internally, in your code).

Inside the WEB-INF directory there are two important directories (classes and lib, and one
important file (web.xml). These are described below.

web.xml

The web.xml file contains information about the web application, which is used by the Java web
server / servlet container in order to properly deploy and execute the web application. For
instance, the web.xml contains information about which servlets a web application should
deploy, and what URL's they should be mapped to. I will not get into more detail about the
web.xml file here. Just know, that it exists.

classes

The classes directory contains all compiled Java classes that are part of your web application.
The classes should be located in a directory structure matching their package structure, just like
if you were to run them directly from the commandline, or package them in a JAR file.

lib

The lib directory contains all JAR files used by your web application. This directory most often
contains any third party libraries that your application is using. You could, however, also put
your own classes into a JAR file, and locate it here, rather than putting those classes in the
classes directory.

Cookies and Servlets

HTTP Cookies are little pieces of data that a web application can store on the client machine of
users visiting the web application. Typically up to 4 kilo bytes of data. This text will explain how
to set, read and remove cookies from inside Java servlets (or JSPs).

Table of contents:

 Java Cookie Example


 Reading Cookies Sent From the Browser
 Cookie Expiration
 Removing Cookies
 Additional Cookie Settings
 Cookie Use Cases

Java Cookie Example


You can write cookies using the HttpServletResponse object like this:

Cookie cookie = new Cookie("myCookie", "myCookieValue");

response.addCookie(cookie);

As you can see, the cookie is identified by a name, "myCookie", and has a value,
"myCookieValue". Thus, you can add many different cookies with different identifies (names).
It's a bit like a Hashtable.

Whenever the the browser accesses the web application it submits the cookies stored on the
client machine to the web application. Only cookies stored by the accessed web application are
submitted. Cookies from other web applications are not submitted.

Reading Cookies Sent From the Browser


You can read the cookies via the HttpServletRequest like this:

Cookie[] cookies = request.getCookies();

Note: the getCookies() method may return null!

Now you can iterate through the array of cookies and find the cookies you need. Unfortunately
there is no way to obtain a cookie with a specific name. The only way to find that cookie again is
to iterate the Cookie[] array and check each cookie name. Here is an example:

Cookie[] cookies = request.getCookies();

String userId = null;


for(Cookie cookie : cookies){
if("uid".equals(cookie.getName())){
userId = cookie.getValue();
}
}

This example finds the cookie with the name "uid" and stores its value in the
If you need to access more than one cookie, you could iterate the Cookie[] array once, and put
the Cookie instances into a Map, using the cookie name as key, and the Cookie instance as value.
Here is how that could look:

Map cookieMap = new HashMap();


Cookie[] cookies = request.getCookies();

for(Cookie cookie : cookies){


cookieMap.put(cookie.getName(), cookie);
}

After this code is executed, you can now access the cookies in the cookieMap using the cookie
names as keys (cookieMap.get("cookieName")).

Cookie Expiration
One important Cookie setting is the cookie expiration time. This time tells the browser receiving
the cookie how long time it should keep the cookie before deleting it.

You set the cookie expiration time via the setMaxAge() method. This method takes the number
of seconds the cookie is to live as parameter. Here is an example:

Cookie cookie = new Cookie("uid", "123");

cookie.setMaxAge(24 * 60 * 60); // 24 hours.

response.addCookie(cookie);

This example first creates a Cookie instance with the name "uid" and the value "123". Second, it
sets the expiration to 24 hours using the setMaxAge() method. 24 hours is 60 seconds x 60
minutes x 24 hours (24 x 60 x 60). Finally the example sets the cookie on the
HttpServletResponse object, so the cookie is included in the response sent to the browser.

Removing Cookies
Sometimes you may want to remove a cookie from the browser. You do so by setting the cookie
expiration time. You can set the expiration time to 0 or -1. If you set the expiration time to 0 the
cookie will be removed immediately from the browser. If you set the expiration time to -1 the
cookie will be deleted when the browser shuts down.

Here is an example:

Cookie cookie = new Cookie("uid", "");

cookie.setMaxAge(0);

response.addCookie(cookie);
If the browser already has a cookie stored with the name "uid", it will be deleted after receiving
the cookie with the same name ("uid") with an expiration time of 0. If the browser did not
already have the cookie stored, this new cookie is just thrown out immediately since its
expiration time is 0.