Request and response

For Servlets to be useful, we need to read the HTTP request, and then generate a response. HTTP Servlets provide two types of instances: HttpServletRequest and HttpServletResponse.

The request parameters

The Servlet framework decodes the HTTP protocol parameters sent by the client into a specific map of key and values. The methods on HttpServletRequest to access these parameters are getParameter(), getParameterNames(), and getParameterMap(). The getParameter() method returns the first value in an array of the query string data values. This is because the HTTP standard allows an HTTP request to be formed with multiple parameter associations.

To retrieve a CGI query data in a URI, such as /fooAction?name=Mary&bus=249, we can write a code like the following:

HttpServletRequest request = ...
String name = request.getParameter("name");
int busNumber = Integer.parseInt(request.getParameter("bus"));

The Servlet framework does not allow setting of the parameters.

Headers

Every HTTP request usually has header information, which describes the client-side information relevant to the user: the invocation method, date and time, the acceptable content types, cache-control, the user agent, zero or more cookies, an optional authorization, and a whole lot more. The Servlet framework exposes through the HttpServletRequest interface with the methods: getHeader(), getHeaders(), and getHeaderName().

Let's inspect a Servlet that demonstrates reading all the HTTP header information as follows:

@WebServlet(name = "reportHeader", urlPatterns = {"/reportHeaders"},
public class ReportHeaders extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
  throws ServletException, IOException {
    resp.setContentType("text/plain");
    PrintWriter pwriter = resp.getWriter();
    pwriter.printf("Header information:
");
    for (String name: Collections.list(req.getHeaderNames())) {
      pwriter.printf("%s = %s
", name,req.getHeader(name));
      }
    }
  }

The ReportHeader servlet iterates through all of the headers with getHeaders(), which returns Enumeration<String>, and then we use the Java Collection framework to manipulate this type into List<String>. For each key in the collection, we dump the header to the Servlet's response writer.

The request attributes

The request attributes are objects that are associated with the HTTP request, hence they are scoped. The request attributes only live for the lifetime of processing a request through the Servlet framework. The attributes are removed after the response has been sent back to the client. If you remember from Chapter 2, Context and Dependency Injection, this request scope is the reason why there is a @RequestScoped annotation for the bean types.

The request attributes are available on HttpServletRequest with the methods getAttribute(), getAttributeNames(), and setAttribute(). The attributes are useful for passing the attributes from one Servlet instance. The Servlet framework provides a RequestDispatcher instance to forward a request on to another or include the content from another Servlet.

The following is an example of a Servlet that geolocates a city to a dealer. This use case is a car manufacturer's business:

@WebServlet(name = "carProduct", urlPatterns = {"/carProduct"},
public class CarProduct extends HttpServlet {
  
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
  throws ServletException, IOException {
    String city = req.getParameter("city")
    req.setAttribute("dealerId", findNearestDealerFromCity(city));
    RequestDispatcher rd = req.getDispatcher("/viewDealer")
    rd.forward(req,resp);
    }
  }

The CarProduct Servlet sets a request scope attribute dealerId with the value obtained from the CGI query parameter city. There is a method findNearestDealerFromCity(), we assume, that handles the geolocation search for us. The doGet() method obtains a RequestDispatcher instance from HttpServletRequest, and forwards it to the next Servlet named viewDealer.

Let's review the code for the ViewDealer Servlet as follows:

@WebServlet(name = "viewDealer", urlPatterns = {"/viewDealer"},
public class ViewDealer extends HttpServlet {
  
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
  throws ServletException, IOException {
    String dealerId = (String)req.getAttribute("dealerId");
    /* ... */
    generateContent(req, resp, dealerId);
    }
  }

The subsequent Servlet is able to retrieve the request scope attribute dealerId, and generate the content around this information.

The session attributes

The Servlet framework provides a means to track the requests that emanate from the same device that is operated by a user. Because of the stateless nature of HTTP, the framework associates similar request from the same client and user in either an HTTP cookie or through URL rewriting. For Servlet containers that support HTTPS protocol connections, the Servlet framework will use standard SSL handshake with encrypted key exchange.

A Servlet session has a lifecycle, which is unique to an HTTP client device, and it is a means for data to survive multiple requests to the Servlet container. A session is a scope and a collection name and value attributes. The Servlet sessions can optionally time out with expiration, and if the session does expire, then the servlet container will remove the information.

The session attributes are available in the HttpSession instance with the methods getAttribute(), setAttribute(), and getAttributeNames(). The HttpSession instance acquired from the HttpServletRequest object is like the following code:

HttpServletRequest request = ...
HttpSession session = request.getSession();
CustomerData custData = (CustomerData)
session.getAttribute("customerData");
session.setAttribute("checkoutInfo", "PRIVILEGED");

As with the request scope attribute, we have to cast to a String on the getAttribute() method, because this call returns an Object. The session scope is closely aligned with the CDI @SessionScoped annotation.

The Servlet context attributes

Every Java Servlet has an association to ServletContext, which is shared between all Servlets in the web application. The specification declares a rule: there is one context per web application per JVM. ServletContext is an ideal place to share a cache of read-only values that are used for the entire lifecycle of the application.

In the JSF, JSP, and CDI specifications, ServletContext is known as the application scope. The CDI @ApplicationScoped corresponds with this unique instance. The key methods for the ServletContext interfaces are getAttribute(), setAttribute(), and getAttributeNames().

Here is a small illustration of the application-wide Servlet loading static data, which is supposed to be read-only. ServletContextDemo is as follows:

@WebServlet(name = "servletContextDemo", urlPatterns = {"/servletContextDemo"},
public class ServletContextDemo extends HttpServlet {
  @Override
  public void init(ServletConfig config) {
    config.getServletContext()
    .setAttribute("dataValues", Arrays.asList(1,2,3,5,8,13,21,34,55,89));
    }
  
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
  throws ServletException, IOException {
    resp.setContentType("text/plain");
    PrintWriter pwriter = resp.getWriter();
    List<Integer> series = (List<Integer>)getServletContext()
    .getAttribute("dataValues");
    pwriter.printf("series=%s
", series);
    }
  }

During initialization of ServletContextDemo, we store the Fibonacci series as an integer collection inside ServletContext, which we can access from the ServletConfig instance. When the user invokes HTTP GET on this Servlet, we retrieve the data series from ServletContext, and send its contents as the response. Inside the doGet() method, we access ServletContext from HttpServletRequest.

Redirecting the response

There are occasions in a web application where the response must be redirected to another location. The Servlet framework sends an HTTP URL redirection to the client (web browser) with a URL that informs where to get the content. We can write the Servlet code to do that as follows:

HttpServletResponse httpServletResponse = httpServletResponse.sendRedirect(httpServletResponse.encodeRedirectURL(httpServletRequest.getContextPath()+ "/carProduct"));

This code extraction redirects the client to the earlier CarProduct Servlet. Because URL redirects can go to any site on the Internet, for example, http://www.bbc.co.uk/news, we must add the web application context path to the URI. After issuing a redirect, the HttpServletResponse instance will be in an undefined state. It is a good practice to encode the URL path with the convenience call encodeRedirectURL().

Many developers apply the technique of POST-REDIRECT-GET. This design pattern effectively avoids returning a rendered web page directly for an incoming request and instead instructs the web browser to load a different the page with a follow up HTTP GET request.. This is an advanced technique out-of-scope for discussion in this book.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.239.103