Servlets

Servlet Life Cycle:

Load Servlet 
Servlet Container loads the Servlet class.
Create Instance of Servlet
After loading, Container creates instance of Servlet. Most Containers create only a single instance of the Servlet and all the concurrent requests are executed for the same 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. init parameters can be configured in the web.xml
Call the Servlets service() Method
For every request received to the servlet, the servlets service() method is called. For HttpServletsubclasses, 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.

Servlet chaining 

Servlet chaining is a technique in which two or more servlets can cooperate in servicing a single request. In servlet chaining, one servlet's output is the input of next servlet. This process continues until the last servlet is reached. Its output is then sent back to the client. We are achieving Servlet Chaining with the help of RequestDispatcher


Two Ways to Chain Servlets

In Servlets/JSPs, there are two ways to achieve servlet chaining using javax.servlet.RequestDispatcher.include() method and forward() method as below:
Include:

RequestDispatcher rd = req.getRequestDispatcher("Servlet2");
rd.include(req, resp);
Forward, where req is HttpServletRequest and resp is HttpServletResponse:

RequestDispatcher rd = req.getRequestDispatcher("Servlet3");
rd.forward(req, resp);
In JSPs, the above code would look like this:
 
RequestDispatcher rd = request.getRequestDispatcher("Servlet4");
rd.forward(request, response);
When you use servlet chaining, you delegate the responsibility of generating the response to the next servlet in the chain.
But, suppose you have some data generated by current servlet that will be required by next servlet. How would you pass it?

You could keep it in the session, but you would need to remove it from that session after you fetch it in next servlet—otherwise your session will have useless data once your request is complete. Not only does this add overhead, but it also makes your next servlet dependent on session tracking.

You can attach your additional data with the request that you are passing to next servlet:


RequestDispatcher rd = req.getRequestDispatcher("Servlet3");
req.setAttribute("key1", value1);
req.setAttribute("key2", value2);
rd.forward(req, resp);
In the above code, req is HttpServletRequest and resp is HttpServletResponse. The code attaches two data items, value1 and value2, with the req object. Use the following code to access this value in the next servlet (Servlet3 in the example):

Object val1 = req.getAttribute("key1");
Object val2 = req.getAttribute("key2");

This attaches two data items (value1 and value2) with the HttpServletRequest object and forwards them to Servlet3. Servlet3 reads them from the HttpServletRequest and uses them.  

loadonstartup element of web.xml:


       The load-on-startup element indicates that this servlet should be loaded (instantiated and have its init() called) on the startup of the web application.
 The optional contents of these element must be an integer indicating the order in which the servlet should be loaded. If the value is a negative integer, or the element is not present, the container is free to load the servlet whenever it chooses.

If the value is a positive integer 128  or 0, the container must load and initialize the servlet as the application is deployed. The container must guarantee that servlets marked with lower integers are loaded before servlets marked with higher integers. The container may choose the order of loading of servlets with the same load-on-start-up value.  

ServletConfig vs ServletContext

ServletConfig as the name implies provide the information about configuration of a servlet which is defined inside the web.xml file or we can say deployment descriptor.its a specific object for each servlet.

ServletContext is application specific object which is shared by all the servlets. It belongs to one application in one JVM . this is single object which represent our application and all the servlets access application specific data using this object.  


response.sendRedirect() vs requestDispatcher.forward()

To simply explain the difference, response.sendRedirect("login.jsp"); doesn't prepend the contextpath (refers to the application/module in which the servlet is bundled)

but, whereas request.getRequestDispathcer("login.jsp").forward(request, response);
will prepend the contextpath of the respective application

Furthermore, Redirect request is used to redirect to resources to different servers or domains. This transfer of control task is delegated to the browser by the container. That is, the redirect sends a header back to the browser / client. This header contains the resource url to be redirected by the browser. Then the browser initiates a new request to the given url.

Forward request is used to forward to resources available within the server from where the call is made. This transfer of control is done by the container internally and browser / client is not involved.

Servlet Concurrency Issues:

A Java servlet container / web server is typically multithreaded. That means, that multiple requests to the same servlet may be executed at the same time. Therefore, you need to take concurrency into consideration when you implement your servlet.

To make sure that a servlet is thread safe, there are a few basic rules of thumb you must follow:

  • Your servlet service() method should not access any member variables, unless these member variables are thread safe themselves.
  • Your servlet service() should not reassign member variables, as this may affect other threads executing inside the service() method. If you really, really need to reassign a member variable, make sure this is done inside a synchronized block.
  • Rule 1 and 2 also counts for static variables.
  • Local variables are always thread safe. Keep in mind though, that the object a local variable points to, may not be so. If the object was instantiated inside the method, and never escapes, there will be no problem. On the other hand, a local variable pointing to some shared object, may still cause problems. Just because you assign a shared object to a local reference, does not mean that object automatically becomes thread safe.

The request and response objects are of course thread safe to use. A new instance of these are created for every request into your servlet, and thus for every thread executing in your servlet.