Wednesday, December 31, 2014

Inter servlet communication in Java

Major reasons to use inter servlet communication
  • Direct Servlet manipulation/handling: One servlet can access to other loaded servlets on the server and perform some task. One servlet obtains information about other servlets through ServletContext object.
  • getServlet() method returns the servlet of given name
    • public Servlet ServletContext.getServlet(String name) throws ServletException
  • Specified name can be servlet's registered name or class name
  • getServlet("file") returns different instance than getServlet("com.sun.server.webserver.FileServlet") because server maintains one servlet instance per name
  • getServlets() method return enumeration of all servlet objects loaded in current ServletContext.
  • Generally there are only one ServletContext object but for security or other reasons there can be many

Example

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
 
public class Loaded extends HttpServlet{
public void doGet(HttpServletRequest request, HttpServletResponse response) 
throws ServletException, IOException{
    response.setContentType("text/html"); 
    PrintWriter out = response.getWriter(); 
    ServletContext context = getServletContext();
    Enumeration names = context.getServletNames();
    while (names.hasMoreElements()){
      String name=(String)names.nextElement();
      Servlet servlet =context.getServlet(name);
      out.println("Servlet name: "+name);
      out.println("Servlet class: "+ servlet.getClass().getName());
      out.println("Servlet info: "+ servlet.getServletInfo());
}}}

Servlet reuse

One servlet can reuse the abilities (public methods) of another servlet. There is challenge though for using methods of unloaded servlets.

Servlet collaboration

Collaboration is done through information sharing. Collaborating servlets can share data directly through method invocations. Servlets must know each other for collaboration. Collaboration can be done through following two methods

Collaboration using system property list

Java's system wide properties list found in java.lang.System class. This list holds standard system properties like java.version, path.separator and other application specific properties. The properties can be accessed by other servlets running on the same JVM. Property class is string based ie key and values are strings.
  • System.getProperties().put("key","value") is called to add or change a property
  • String value=System.getProperty("key") is used to access the value of key
  • System.getProperties().remove("key") is used to remove the property

Collaboration through a shared object

Shared objects can hold pool of shared information and make it available to other servlets when needed. System properties list is special case example of shared object. The shared object often incorporates business logic to manipulate the data. The business logic also protects data by defining mutators, accessors and other methods. Garbage collector might reclaim the shared object when it is not referenced by a loaded servlet. To keep garbage collector at bay, every servlet using a shared object should save reference to the object.

Database Connectivity with servlets

Every programmer needs to connect to database for storing and retrieving the information. In Java, database connection is made easy by Java Database Connectivity (JDBC) API.

  • Database connectivity is done through JDBC (Java Database Connectivity)
  • JDBC is well defined database independent database connectivity API
  • Middle tier i.e. stays between servlet and database

Example: Code implementing Phone book in Java through JDBC


import java.io.*;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;
 
 public class DBPhoneLookup extends HttpServlet{
  public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ 
    //Define required variables
    Connection con = null;
    Statement stmt = null;
    RequestSet rs = null;
    response.setContentTyp("text/html");
    PrintWriter out = response.getWriter();

    try{
      //load and register oracle driver
      Class.forName(sun.jdbc.odbc.JdbcOdbcDriver);

      //get a connection to the database
      Connection con = DriverManager.getConnection(jdbc:odbc:Access);

      //Create a statement object
      stmt = con.createStatement;

      //execute SQL query and geta a result set
      rs = stmt.executeQuery("select name, address from customer");

      //display result set
      out.println("<html><head><title>Employee phonebook</title></head><body><ul>");

      while(rs.next())
        out.println("<li>"+rs.getString("name")+", "+rs.getString("address"));
 
      out.println("</ul></body></html>");

    } catch(ClassNotFoundException e) {
      out.println("Couldn't load database driver: "+ e.getMessage());
    } catch(SQLException e) {
      out.println("SQL Exception: "+ e.getMessage());
    }

    finally {
      try{
        if (con !=null) con.close();
      } catch(SQLException e) {
      out.println("SQL Exception: "+ e.getMessage());
    }
}}

Session tracking with persistent cookies in Java

Cookies are used to store certain client information in client side. It is created by server, sent to browser, and browser manages cookies to identify itself to the server when re-connected.
  • Cookie is a bit of information sent by a web server to a browser
  • Browser stores cookie on client machine and later sends back to server each time it access page on that server
  • Generally used to identify client, list client's preferences and used for session tracking
  • Some browsers don't support or accept cookies
  • javax.servlet.http Cookie class is used for working with cookies.
  • Cookies can be created with Cookie() constructor with initial name and value
    • public Cookie(String name, String value)
  • Servlet can send a cookie to the client by passing a Cookie object to addCookie() method of HttpServletResponse
    • public void HttpServletResponse.addCookie(Cookie cookie)
  • Cookies are sent using HTTP headers so they should be added to response before any content is sent to the client
  • Multiple cookies can be added to a response
  • Browsers generally accept 20 cookies per site and 300 cookies per client and may limit cookie size to 4KB

Example: Set cookie with initial id field

//set cookie with initial id field
Cookie cookie=new Cookie("id","123"); 
 
//add cookie to the response object
response.addCookie(cookie); 
 
//retrieve cookie from the client
Cookie[] cookies = request.getCookies(); 
 
if(cookies!=null){
  for(int i=0;i<cookies.length;i++){
    String name=cookies[i].getName();
    String value=cookies[i].getValue();
}}

Some methods of cookies used for session tracking

  • Maximum expiry age in seconds; negative value specifies default and zero value specifies, cookie is deleted when browser exists
    • public void Cookie.setMaxAge(int expiry)
    • public int getMaxAge()
    • public void Cookie.setVersion(int v)
  • Return domain of the cookie, null if not defined
    • public String getDomain()
  • Set domain attribute to define which hosts the cookie should be presented to by the client ( eg .example.com)
    • public void Cookie.setDomain(String pattern)
  • Indicate the user agent that this cookie should only be sent via secure channel like HTTPS
    • public void Cookie.setPath(String uri)
  • Assign new value to cookie
    • public void Cookie.setValue(String newValue)
  • Return the value of cookie
    • public String getValue()

Example session tracking using persistent cookie. Implementing shopping cart in Java

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class ShoppingCartViewerCookie extends HttpServlet {
  public void doGet(HttpServletRequest request, HttpServletResponse response) 
   throws servletException, IOException{
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();

    //get the current sessionid if exists by searching the received cookies
    String sessionid=null;
    Cookie[] cookies = request.getCookies();

    if(cookies!=null){
      for(int i=0;i<cookies.length;i++){
        if(cookies[i].getName().equals("sessionid")){
          sessionid=cookies[i].getValue();
          break();
        }
      }
    }
 
    //set session id if it was not found and send it to client with response
    if(sessionid==null){
      sessionid=generateSessionId();
      Cookie c = new Cookie("sessionid",sessionid);
      response.addCookie(c); 
 
    //display information about shopping cart after setting sessionid
    out.println("<html><head><title>Shopping cart</title></head><body>");

    //cart items are associated with session id
    String items = getItemsFromCart(sessionid);
    out.println("<h1>You have following items in your shopping cart</h1>");

    if(items==null){
      out.println("No items");
    } else {
      out.println("<ul>");
      for(int i=0; i<items.length;i++)
        out.println("<li>"+ items[i] + "</li>");
      out.println("</ul>");
    }

    //Ask if client want more item or check out
    out.println("<form action=\"/servlet/ShoppingCart\" method="POST">");
    out.println("<input type=submit value=\"Add more items to cart\">");
    out.println("<input type=submit value=\"Check out\">");
    out.println("</form>");
}}

Session Tracking in HTTP Servlet Programming in Java

HTTP is stateless protocol. A web server can keep track of clients and distinguish them by using session. This helps in delivering customized services for each client. The server identifies each client with session tracking
  • Each client is associated with javax.servlet.http.HttpSession object
  • Any set of arbitrary java objects can be saved in session object
  • getSession() method is used to retrieve the current HttpSession object. This method is in request object.
    • public HttpSession HttpServletRequest.getSession() //create new if not exist
    • public HttpSession HttpServletRequest.getSession(boolean create)
    • This gets or creates new one if create argument is set and returns HttpSession object otherwise return null
  • putValue() method is used to add data to HttpSession object
    • public void putValue(String name, Object value)
  • getValue() method is used to retrieve data from the session object
    • public Object HttpSession.getValue(String name)
  • getValueNames() method is used to retrieve array of all name-value pairs bound to session
    • public String[] HttpSession.getValueNames()
  • removeValue() method removes values from the session
    • public void HttpSession.removeValue(Strin name)
  • All these methods throw throws java.lang.IllegalStateException

Example implementing hit counter using session tracking in Java

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class SessionTracker extends HttpServlet {
  public void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws servletException, IOException{
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    //gets the current session object, create one if necessary (true)
    HttpSession session = request.getSession(true);
    //increment the hit count ofr this page. The value is saved
    //in this client's session under the name "tracker.count"
    Integer count = (Integer)session.getValue("tracker.count");
    If (count==null)
      count=new Integer(1);
    else
      count = new integer(count.intValue()+1);
    session.putValue("tracker.count",count);
    out.println("<html><head><title>Session tracker</title></head>");
    out.println("<body><h1>Session Tracking Demo</h1>");
    out.println("You visited this page "+ count + " times");
    out.println("<h2>Your Session Data</h2>");
    String[] names = session.getValueNames();
    for (int i=0;i<names.length;i++){
      out.println(names[i]+": "+session.getValue(names[i]+"<br>");
    }
    out.println("</body></html>");
}}

Servlet Life cycle in Java HTTPServlet

We generally start writing Java code with main() method. Servlets don't contain this method. Beginners are confused how this servlet runs. Before we start coding servlets, we need to know how it operates. What stages does it pass through. With this information, we can understand the inner working of servlets.
  • Servlets run inside servlet container, so creation and destruction of servlet is the responsibility of servlet container.
  • Servlet life cycle is defined by javax.servlet.Servlet interface, which defines how it is initialized, how it handles request and response, and how it is taken out of service
  • init() and destroy() methods are used by servlet container to do the task
  • life cycle can be understood by following flow
    • Servlet class
    • Instantiating and loading: servlet engine can instantiate more than one servlet instance
    • Initialization: (servlet config) init() method
    • Ready service method: A service method executes for each servlet interface
    • Destruction: destroy() method
    • Garbage collection: Server no longer has reference to the object

In servlet Life Cycle, the major stages are

  • Servlet Initialization: Servlet initialization is done by calling servlet’s constructor and init() method only once during servlet life cycle. Initialization is done automatically when needed or at startup if container is specifically told to load at startup. It is started automatically as soon as request is made e.g. opening database connection. It is loaded at startup if load-at-startup tag is set to nonzero.
  • Servlet Execution: No new instance of servlet is created at this stage. However, request and response objects are created, which are used to communicate with the one that is requesting. Servlet container forwards all the requests to servlet’s service() method. This service() method is executed every time request is made. The HttpServlet class breaks this service() method to more useful doGet(), doPost(), doPut(), doDelete(), doTrace(), doOptions() etc methods according to HTTP request. Only the required methods need to be overridden to carry out our task.
  • Servlet Destruction: When application is stopped or servlet container shuts down, the servlet is destroyed by calling destroy() method. This method frees the resources used by servlet.
  • Here, init() and destroy() methods are called only once during life cycle while service() method is called as many time as required after initialization.

Servlet showing life cycle in Hello World example

include java.io.*
include javax.servlet.*
include javax.servlet.http.*

public class HelloWorld extends HttpServlet {

    public String name = "Hello World"
    @Override
    public void init() throws ServletException{
        System.out.println("Method init() called");
    }
 
    //@Override is needed to inform compiler that method is overridden
    @Override
    public void destroy() {
        System.out.println("Method destroy() called");
    }

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException,IOException {
        response.setContetnType("text/html");
        PrintWriter out=getWriter();
        out.println("<html><head><title>");
        out.println(name);
        out.println("</title></head>");
        out.println("<body><h1>Hello World</h1>You are welcome!</body></html>");    
    }
 
    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws IOException, ServletException {
         doGet(request, response)
    }
}

What is java servlet and how to write a servlet

Servlets are like regular java program but with peculiar characteristics. It is generally intended to run in web server and give web services to the clients. Servlets are made to handle the HTTP requests like GET and POST. These requests are handled by overriding the doGet() and doPost() methods in Service() method of javax.servlet.Servlet interface.
  • Do not have main() method; runs in servlet container on web server like tomcat
  • Implements javax.servlet.Servlet interface of J2EE
  • Implements http requests like get, post, put, delete etc by overriding doGet(), doPost() methods of HttpServlet class
  • doGet() and doPost() methods in servlet gets parameters from browser in HttpServletRequest and sets parameters of HttpServletResponse which can be used by JSP to display variables  and render html in User interface

get request —————>|———————— |               overrides
get response <————  | Servlet implements |<———>doGet()
                                         | Service() method    |
post request  ————> | of Servlet class        |<———>doPost()
post response <————|________________ |

Servlet Hello World Example

It is very easy to program servlet, we can program it only with the knowledge of which class to inherit and which methods to override.

include java.io.*
include javax.servlet.*
include javax.servlet.http.*
 
public class HelloWorld extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException,IOException {
        response.setContentType("text/html");
        PrintWriter out=getWriter();
        out.println("<html><head><title>Hello World</title></head>");
        out.println("<body><h1>Hello World</h1>You are welcome!</body></html>");    
}}

getWriter() method of the HTTPServletResponse class to set the output to response object. In the last two lines, HTML output is printed, so that browser receiving that can render proper HTML.

Two important interfaces included in servlet API

HttpServletRequest interface

When any request is made by client, the servlet container makes request object and passes to service() method of the servlet. This interface encapsulates functionality for a request object passed to HTTP servlet. Provides access to input stream and allows servlet to read data from clients like from forms. It contains following methods

public Cookie[] getCookies()
public String getQueryString()
public HttpSession getSession() //creates session if no established session
public HttpSession getSession(boolean create) //creates session if arg is set
public String getHeader(String name)
public String getParameter(String name)

HttpServetResponse interface

Encapsulates the functionality of response object returned to the client by the servlet. Provides access to output stream and allows servlet to send data to clients. It contains following methods to formulate response to client

public void addCookie(Cookie cookie);
public void sendError(int statusCode) throws IOException
public void sendError(int statusCode, String message) throws IOException
public PrintWriter getWriter() //Outputs character based output data
public ServletOutputStream getOutputStream() //outputs byte based binary data
public void sendRedirect(String location) throws IOException //temp redirect response