Servlet

Why Servlet ?

Dynamic web applications requires processing of request information, accessing other resources and generating response content dynamically. CGI (Common Gateway Interface) technology was being used to generate dynamic contents.

CGI Technology

CGI technology was being used to provide dynamic content to the user. It executes a program that resides in the server. It can access databases to produce relevant dynamic content. Program written in server can be written in native OS language such as C++. CGI can be implemented using any programming language but mostly CGI is implemented in Perl.

Drawbacks of CGI Technology

  • For each request CGI server receives, new OS process is created
  • As number of requests increases, response time also increases
  • Program executed by CGI scripts are written in native language (C, C++ or Perl), so it is platform dependent

Need of better web technology like servlet

A better web technology was required to overcome the drawbacks of CGI technology. A technology that provide lightweight, robust and portable. Servlet, being developed on Java Technologies, provides all the capabilities of Java and brings ultimate solution to develop dynamic web applications.

Servlet is not limited to only web technology, it can be used by any request-response programming model.

Servlet vs CGI

What is Servlet ?

  • Servlet is Web technology which is used to develop server side web components for dynamic web applications.
  • Java Servlet technology provides dynamic, user-oriented content in web applications using a request-response programming model.
  • A servlet is a Java programming language class used to extend the capabilities of servers that host applications accessed by means of a request-response programming model.
  • Although Servlets can respond to any type of request, they are commonly used to extend the applications hosted by web servers.
  • For such applications, Java Servlet technology defines HTTP-specific servlet classes.
  • The javax.servlet and javax.servlet.http packages provide interfaces and classes for writing servlets.
  • All servlets must implement the Servlet interface, which defines lifecycle methods.
  • When implementing a generic service, you can use or extend the GenericServlet class provided with the Java Servlet API.
  • The HttpServlet class provides methods, such as doGet and doPost, for handling HTTP-specific services

What it does?

  • Receives different type of requests(like GET, POST)
  • Process the request data
  • Prepares HTML response

Web Server => Web Container => Web applications => Web Components

Servlet API

Servlet Lifecycle

The lifecycle of a Servlet is controlled by the container in which the Servlet has been deployed. All request reached to the container and mapped to Servlet using URL pattern. Once mapping Servlet found, web container performs the following steps:

Step 1

If instance of the servlet does not exists, then web container

  1. Loads the Servlet class
  2. Creates instance of the loaded servlet class by calling new() method
  3. Initializes the servlet instance by calling the init() method

Step 2

Container invoked service method(doGet(), doPost(), service() etc), passing request and response objects

Step 3

If it needs to remove the servlet, container finalizes() the servlet by calling Servlet’s destroy() method

Creating and Initializing a Servlet

  • Use @WebServlet annotations to define a servlet component in web application
    • It’s a class level annotation and contains metadata about the servlet being declared
    • Annotated servlet must declare at least one URL pattern (urlPattern=”pattern” or value=”pattern”)
    • Other attributes are optional with default setting
  • Class annotated with @WebServlet must extend javax.servlet.http.HttpServlet class
  • Example:
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
@WebServlet("/report")
public class MoodServlet extends HttpServlet {
}

Note:

  • Web container Loads -> Instantiate -> Initializes the servlet and then Delivers requests to it from Clients
  • This process can be customized by
    • Allowing servlet to read configuration data
    • Initialize resources and
    • Perform any one time activities
  • This can be done by
    • Either overriding init methos of Servler interface
    • Or specifying the initParam attribute of the @WebServlet annotation
      • intiParam attribute contains @WebInitParam annotation
      • If it cannot completes its initialization process, servlet throws an UnavailableException
  • Use initialization parameter to provide data needed by a particular servlet
  • In contrast, a context parameter provide data that is available to all components of the Web Application

Writing Service Methods

Service method is any method in servlet class that provides a service to client. Examples of service methods are service method of GenericServlet and doGet, doPost, doPut etc methods of HttpServlet . Any other protocol-specific methods defined by a class that implements Servlet

The general pattern of service method is to

    1. Extract information from servlet
    2. Access external resources
    3. Populate the response based in request information, For HTTP servlets, the correct way for populating the response is to do the following
      • Retrieve an output stream from the response e.g. PrintWriter pw = response.getWriter();
      • Fill in the response headers
      • Write any body content to the output stream

Note:

Response headers must always be set before the response has been committed. The Web container will ignore any attempt to set or add headers after the response has been committed.

Getting information from Requests

A request contains data passed between client and the servlet. All requests implements ServletRequest interface. ServletRequest interface defines methods for accessing the following information.

    • Parameters(used to convey information between clients and servlets)
    • Object-valued attributed, typically used to pass information between
      • Web Container and a servlet
      • Collaborating servlets (i.e. one servlet to another)
    • Information about Protocol used to communicate the request
    • Information about Client and server involved in the request
    • Information relevant to localization
  • This data can also be retrived as input stream but needs to be parsed manually
    • To read character data, use BufferedReader objects by request’s getReader
    • To read binary data, use ServletInputStream object by getInputStream
  • HTTP servlets are passed an HTTP request object, HttPServletRequest
    • It contains request URL, HTTP header, query-string and so on
    • An HTTP request URL contains following parts
    • http://[host]:[port][request-path]?[query-string]
    • The request path is futher composed of following elements
      • Context path
      • Servlet path
      • Path info
    • You can use the getContextPath, getServletPath, and getPathInfo methods of the HttpServletRequest interface to access this information.
    • Except for URL encoding differences between the request URI and the path parts, the request URI is always comprised of the context path plus the servlet path plus the path info.
    • Query strings are composed of a set of parameters and values. Individual parameters are retrieved from a request by using the getParameter method. There are two ways to generate query strings.
      • A query string can explicitly appear in a web page.
      • A query string is appended to a URL when a form with a GET HTTP method is submitted.

Constructing Response

A response contains data passed between a server and client. All responses implements ServletResponse interface. This interface defines methods that allows you to do the following

    1. Retrieve an output stream to use to send data to the client
      • To send character data, use PrintWriter returned by response’s getWriter
      • To send binary data in a MIME body respose, use ServletOutputStream returned by getOutputStream
      • To mix binary and text data, user ServletOutputStream and manage the character section manually
    2. Indicate the content type (for example text/html)
      • To do this setContentType(String) method is available
      • This method must be called before response is committed
    3. Indicate whether to buffer output with the setBufferSize(int) method
      • By default, any content written to the output stream is immediately sent to the client
      • Buffering allows content to be written before anything is sent back to the client, thus providing the servlet with more time to set appropriate status codes and headers or forward to another web resource. The method must be called before any content is written or before the response is committed.
    4. Set localization information such as locale and character encoding
    5. HTTP response objects, javax.servlet.http.HttpServletResponse, have fields representing HTTP headers, such as the following.
      • Status codes, which are used to indicate the reason a request is not satisfied or that a request has been redirected.
      • Cookies, which are used to store application-specific information at the client. Sometimes, cookies are used to maintain an identifier for tracking a user's session

Parameters

  • Parameters are used to pass data among different web components
  • These are name-values pairs i.e. value can easily be accessed by using it’s corresponding name
  • Once set, cannot be modified hence parameters are read-only
  • Web container stores parameters in it’s corresponding objects

Types of parameter

There are mainly three type of parameters

  1. ServletRequest parameters
  2. ServletConfig parameters
  3. ServletContext parameters

1. ServletRequest parameters

  • Web client sends data to Web server in request header or body as query string
  • Web container collects this query string data from request header/body and stores in HttpServletRequest object as parameter(s)
  • These parameters and associated values can be fetched using HttpServletRequest object
  • There are mainly three ways to fetch values from these parameters

Using getParameter and getParameterValues

String name = request.getParameter("name");
String jModules[] = request.getParameterValues("jModules");

Using getParameterMap

Map<String, String[]> map = request.getParameterMap();
   Set paramNames = map.keySet();
  Iterator it = paramNames.iterator();
  while (it.hasNext()) {
   String paramName = (String) it.next();
   Object paramValue = map.get(paramName);
   String[] paramValueArray = (String[]) paramValue;
   for (int i = 0; i < paramValueArray.length; i++) {
    out.println("<label>" + paramValueArray[i] + " </label>");
   }
   out.println("<br>");
  }

Using getParameterNames

Enumeration<String> paramEnum = request.getParameterNames();
   List<String> paramList = Collections.list(paramEnum);
  for (String param : paramList) {
   out.println(request.getParameter(param) + "<br>");
  }

2. ServletConfig parameters

  • ServletConfig is an interface in javax.servlet package
  • Web container vendor provides implementing class for the same
  • Each servlet has its own ServletConfig object, which is not sharable with other servlets
  • Data that is common for all user but specific to particular servlet can store in ServletConfig
  • This data can be specified in either web.xml or using @WebInitParam annotation
@WebServlet(urlPatterns = { "/EnrollmentJavaServlet" }, initParams = {
   @WebInitParam(name = "trainerName", value = "Atul", description = "Name of Java trainer"),
  @WebInitParam(name = "trainerEmailId", value = "contact@atuldwivedi.com", description = "Email ID of Java trainer") })
public class EnrollmentJavaServlet extends HttpServlet {
...
}
  • Web container reads this data from web.xml/annotation and set in ServletConfig object
  • ServletConfig object can be obtained either by getServletConfig of Overriding init method
ServletConfig cfg = getServletConfig();

or

@Override
  public void init(ServletConfig config) throws ServletException {
  // TODO Auto-generated method stub
  super.init(config);
  this.cfg = config;
  this.ctx = config.getServletContext();
 }

Fetch ServletConfig parameters using getInitParameter

//Get config parameter values
ServletConfig cfg = getServletConfig();
String trainerName = cfg.getInitParameter("trainerName");
String trainerEmailId = cfg.getInitParameter("trainerEmailId");

Fetch ServletConfig parameter using getInitParameterNames

Enumeration<String> paramEnum = request.getParameterNames();
   List<String> paramList = Collections.list(paramEnum);
  for (String param : paramList) {
   out.print("<label>" + param + ": </label><b><label>"
     + request.getParameter(param) + "</label></b> <br>");
  }

3. ServletContext parameters

  • ServletContext is an interface in javax.servlet package
  • Web container vendor provides implementing class for the same
  • One Web application has only one ServletContext object i.e. one for all servlets
  • Data is shared among all web components
  • Data that is common among all users and across all servlet can be stored in ServletContext
  • ServletContext object can be obtained from ServletConfig.getServletContext
  • This data can be specified in web.xml
  <context-param>
    <param-name>institute</param-name>
    <param-value>Info Campus</param-value>
  </context-param>

Fetch ServletContext parameters using getInitParameter

//Get context parameter values
ServletContext ctx = cfg.getServletContext();
String instituteName = ctx.getInitParameter("institute");

Fetch ServletContext parameters using getInitParameterNames

ServletContext ctx = cfg.getServletContext();
   Enumeration<String> ctxParamEnum = ctx.getInitParameterNames();
  List<String> ctxParamList = Collections.list(ctxParamEnum);
  for (String ctxParam : ctxParamList) {
   out.print("<label>" + ctxParam + ": </label><b><label>"
     + ctx.getInitParameter(ctxParam) + "</label></b> <br>");
  }

Request Dispatcher

  • RequestDispatcher is and interface in javax.servlet package
  • It is used to dispatch the request from one web component to other using forward() method
  • It can also include other web component in Servlet like HTML, JSP using include() method
  • RequestDispatcher object can be obtained using request.getRequestDispatche()
RequestDispatcher rd = request.getRequestDispatcher(path + page);
  • RequestDispatcher has two methods
    • public void forward(ServletRequest req, ServletResponse res)
    • public void include(ServletRequest req, ServletResponse res)

The forward() method

  • This method forward requests from
    • Servlet to HMLT similarly JSP to HTML
    • Servlet to JSP similarly JSP to JSP
    • Servlet to Servlet similarly JSP to Servlet
  • It is used to provide programmatically access to resources placed inside WEB-INF
  • Once servlet can have multiple forward() placed in conditional blocked such that only one will be executed otherwise java.lang.IllegalStateException will be thrown
  • After forwarding statement servlet can have following statements to execute but those statements cannot write any content to response stream

Syntax

RequestDispatcher rd = request.getRequestDispatcher(path + page);
 rd.forward(request, response);

Example

A typical example of using RequestDispatcher.forward in login scenario where if login is successful, forward the request to home page otherwise forward it to error page. Below is the code snippet for the same:

protected void doPost(HttpServletRequest request,
    HttpServletResponse response) throws ServletException, IOException {
  String userName = request.getParameter("userName");
  String password = request.getParameter("password");

  if (userName.equals(password)) {
   page = "home.html";
  } else {
   page = "error.html";
  }

  RequestDispatcher rd = request.getRequestDispatcher(path + page);
  rd.forward(request, response);
 }

The include() method

  • Used to include other resources like servlet and/or JSP in response
  • Unlike forward(), servlet can have many include() statements and all will be executed

Syntax

RequestDispatcher rd1 = request.getRequestDispatcher(path+"header.html");
rd1.include(request, response);

Example

A typical example of using include() method is to include header and footer in the web page and may be menu section in the page.

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  String page = request.getParameter("page");
  
  RequestDispatcher rd1 = request.getRequestDispatcher(path+"header.html");
  rd1.include(request, response);
  
  RequestDispatcher rd2 = request.getRequestDispatcher(path+page+".html");
  rd2.include(request, response);
  
  RequestDispatcher rd3 = request.getRequestDispatcher(path+"footer.html");
  rd3.include(request, response);
 }

Send Redirect

  • Redirects the control to another web component
  • This includes browser refresh or url change

Syntax

response.sendRedirect("index.html");

Example

protected void doGet(HttpServletRequest request,
    HttpServletResponse response) throws IOException, ServletException {
  String enteredURL = request.getParameter("url");

  if (enteredURL == null || enteredURL.length() == 0) {
   RequestDispatcher rd = request.getRequestDispatcher("error.html");
   rd.forward(request, response);
  } else {
   response.sendRedirect("index.html");
  }
 }

RequestDispatcher.forward v/s HttpServletResponse.sendRedirect

Filters

Why

In the processing of requests by Servlets there may be some tasks that need to be done before and after request processing. These tasks are not intended to be done by Servlets, but are essentials in order to serve the requests.

Tasks need to be done before request processing called request pre-processing. These task also includes cross cutting concerns like security and logging. Eg:

    • Security
    • Logging
    • Authentication and Authorization
    • Session validity

Tasks need to be done after request processing called request post-processing. Eg:

    • Data compression
    • Data encryption or encoding
    • URL rewriting

These tasks can be done in servlet itself but writing code for same task in different servlets may incur maintenance cost. These type of common tasks can be separated from servlet and can be used before servlet start processing request as well as after servlet completes processing of request. To achieve the same Servlet Filters can be used

What

  • Filters are web components like Servlet
  • Web container manages complete life cycle of filters
  • Filter life cycle is same as Servlet except calling service methods containr invokes doFilter method
  • Filters are responsible for request pre-processing and request post-processing
  • Servlets are responsible for core request processing
  • Filters removes pre and post processing code duplication in each servlet

How

Like Servlets mapped towards urls using annotation, Filters can be mapped towards urls and Servlet names with annotation or via configuration in web.xml or by mixing both.

Any class which is a Filter if it

    • Implements javax.servlet.Filter interface
    • Annotated with @WebFilter annotation

Your filter class must has to override Filter life cycle methods

    • public void init(FilterConfig fConfig)
    • public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc)
    • public void destroy()

Syntax

@WebFilter(description = "Demostrate how to use filter", 
urlPatterns = { "*.do" }, 
initParams = { @WebInitParam(name = "filterName", 
        value = "MyFilter", 
       description = "The filter name") })
public class Myfilter implements Filter {
...
}

Example

You may want to capture input parameters and the IP address of the user before servlet start request processing. Once servlet completes request processing you may also want to capture the message being send by the servlet.

public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain chain) throws IOException, ServletException {

  // Pre-processing
  System.out.println(request.getParameter("firstName"));
  System.out.println(request.getParameter("lastName"));
  System.out.println(request.getRemoteAddr());

  // pass the request along the filter chain
  // servlet core request processing - control goes to servlet
  chain.doFilter(request, response);

  // Post-processing
  Object obj = request.getAttribute("msg");
  String msg = obj.toString();
  System.out.println(msg);
 }

Filter life cycle

Life cycle of the Filter is same as the Servlet life cycle except that container will be calling the doFilter() provided by the Filter interface instead for service() method of Servlet. A filter will be having one instance per declaration and like ServletConfig there will be a FilterConfig object injected inside it. FilterConfig holds the reference to ServletContext.

  • All filters will be initialized by container at container start-up
  • At the time of filter initialization
    • Filter class will be loaded
    • Filter instance will be created using default constructor
    • Filter instance will be cast to javax.servlet.Filter
    • FilterConfig object will be create
    • FilterConfig object will be initialized using filter config parameter
    • FilterConfig object will be initialized with ServletContext object
    • Filter.init will be called by passing FilterConfig object
  • User performs pre and post processing in Filter.doFilter by sandwiching chain.doFilter
  • At container shutdown, container calls Filter.destroy to release the resources

Chaining

Servlet Chaining

  • Invoking multiple servlets one after another before sending response is called Servlet chaining.
  • Servlet 1 calls Servlet 2, Servlet 2 calls Servlet 3 and Servlet 3 sends the response

Servlet chaining – Quick points

  • Servlet chaining order cannot be controlled from outside the servlets

Filter chaining

  • Invoking multiple filters one by one as chain is called as Filter chaining
  • Filter chaining order can be controlled from web.xml
  • Filter defined first in web.xml will be executed first

Listeners

  • There are various task that are performed by web container and developer during web application execution cycle
  • Some of these task binds with corresponding events
  • There are listeners provided for each type of event
  • When task is performed, event is triggered, listener listens to these event and react to those events
  • All Listener interfaces and even classes are part of javax.servlet package

How to write listeners

Any class which

  • Implements any Listener interface of javax.servlet package
  • Annotated with @WebListener

is a Listener.

  • Alternatively to the annotation listener can be configured in web.xml
  • All methods of Listener interface must be overridden
  • Container initialized by container at start up

Configure in web.xml

<listener>
   <listener-class>com.atuldwivedi.learnservlet.listener.ContextListener</listener-class>
 </listener>

Configure using annotation

@WebListener
public class ContextListener implements ServletContextListener {
...
}

Example

An example of writing Listener class for ServletContextListener

  • ServletContextListener has two methods
    • public void contextInitialized(ServletContextEvent sce)
    • public void contextDestroyed(ServletContextEvent sce)
  • Both methods need to be overridden in user’s Listener class
  • Below is the code for the same
package com.atuldwivedi.learnservlet.listener;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

/**
 * Application Lifecycle Listener implementation class ContextListener
 * 
 */
@WebListener
public class ContextListener implements ServletContextListener {

  /**
  * Default constructor.
  */
 public ContextListener() {
  // TODO Auto-generated constructor stub
 }

 /**
  * @see ServletContextListener#contextDestroyed(ServletContextEvent)
  */
 public void contextDestroyed(ServletContextEvent arg0) {
  ServletContext ctx = arg0.getServletContext();
  System.out.println(this.getClass().getName() + " contextDestroyed "
    + ctx);
 }

 /**
  * @see ServletContextListener#contextInitialized(ServletContextEvent)
  */
 public void contextInitialized(ServletContextEvent arg0) {
  ServletContext ctx = arg0.getServletContext();
  System.out.println(this.getClass().getName() + " contextInitialized "
    + ctx);
 }

}

Internal working

Container startup

  • Container create ServletContext object
ServletContext sctx = new ServletContextImpl();
  • Initializes sctx with context parameters configured in web.xml
  • Container creates ServletContextEvent object
ServletContextEvent sce = new ServletContextEvent(sctx);
  • Container creates ServletContextListener object
ServletContextListener listener = new ServletContextListenerImpl();
  • Container invokes contexInitialized() method of ServletContextListener
listener.contexInitialized(sce);

Container shut down

  • Container invokes contextDestryed() method of ServletContextListener
    • listener.contextDestroyed(sce);
  • Destroyed the ServletContext object