Recipe 6.3 Including Resources Nested at Multiple Levels in a Servlet


You want to include resources in a servlet that already include servlets, JSPs, or HTML.


Use the javax.servlet.RequestDispatcher.include(request,response) method to include the top-level file. Make sure that error pages are properly configured in web.xml , just in case an exception is thrown in a deep-nested, imported file.


Even though it does not represent the best architectural decision, it is possible for a servlet to include a resource that itself includes another resource, resulting in a number of inclusions taking place beneath the surface. Imagine the Russian dolls that fit inside each other. You unscrew the top half of the dolls, only to find smaller replicas of the dolls nested inside the outer ones. It is not outlandish to think of very complex web pages using HTML frame and table tags, containing headers and footers, with these segments of the page containing other specialized content using an include mechanism. One of the included files nested several levels deep could throw an exception or corrupt the chain of inclusions in some manner. Although there is no foolproof way to defend against this occurrence, for the purposes of debugging, make sure that the web application has an error page configured so that it can display information about the resource that ran into include problems.

This recipe provides an example of a servlet that has three levels of included resources. The outer servlet includes another servlet named Level2 , which includes a JSP level3.jsp , which completes the picture by including the inner servlet, Level4 . Figure 6-3 shows the browser display when a user requests the com.jspservletcookbook.MultipleInc servlet.

Figure 6-3. Three included files in one web page

Example 6-6 shows the servlet code. This servlet is responsible for the first level of text ("Hello from Level 1"), then each of the included resources contributes content to the response.

Example 6-6. The outer included servlet
 package com.jspservletcookbook;               import javax.servlet.*; import javax.servlet.http.*; public class MultipleInc extends HttpServlet {        public void doGet(HttpServletRequest request,        HttpServletResponse response) throws ServletException, {                  response.setContentType("text/html"); out = response.getWriter( );                  out.println("<html>");         out.println("<head>");         out.println("<title>Multiple Includes</title>");           out.println("</head>");         out.println("<body>");         out.println("<h1>Hello from Level 1</h1>");  out.println("This text is displayed at Level 1.");         RequestDispatcher dispatcher = request.           getRequestDispatcher("/level2");         dispatcher.include(request, response);  out.println("</body>");         out.println("</html>");                  }  } 

The code:

 RequestDispatcher dispatcher = request.getRequestDispatcher("/level2");   dispatcher.include(request, response); 

includes the output of the servlet that is mapped to the servlet path /level2 , which Example 6-7 shows (just the doGet method).

Example 6-7. The first inner included servlet
 public void doGet(HttpServletRequest request, HttpServletResponse response) throws  ServletException, IOException {         out = response.getWriter( );         out.println("<h2>Hello from Level 2</h2>");         out.println("This text is included at Level 2.");         //Include the JSP file named "level3.jsp"  try{                  RequestDispatcher dispatcher = request.getRequestDispatcher(           "/level3.jsp");         dispatcher.include(request, response);         } catch (Exception se){                          String context_path = (String) request.getAttribute(               "javax.servlet.include.context_path");             String servlet_path = (String) request.getAttribute(               "javax.servlet.include.servlet_path");             String errMessage = new StringBuffer(               "Exception raised during Level2 servlet include:<br>").                 append("Context path: "+context_path+"<br>").                   append("Servlet path: "+servlet_path).toString( );             throw new ServletException(errMessage);          }  } 

Example 6-7 writes more text to the response, then includes a level3.jsp , like the outer servlet, using a javax.servlet.RequestDispatcher object to initiate including the JSP. The Level2 servlet does some other stuff with a try/catch block and request attributes, in order to demonstrate the handling of exceptions that may be thrown during include operations.

According to the JSP API specification, included resources have access to five request attributes:

  • javax.servlet.include.request_uri

  • javax.servlet.include.context_path

  • javax.servlet.include.servlet_path

  • javax.servlet.include.path_info

  • javax.servlet.include.query_string

In the catch block, the Level2 servlet gets the value of two of these request attributes with:

 String context_path =   (String) request.getAttribute("javax.servlet.include.context_path"); String servlet_path =   (String) request.getAttribute("javax.servlet.include.servlet_path"); 

In the catch block, the Level2 servlet then throws a new ServletException with the attribute values as part of the exception message. An error page configured for the web application displays information about the exception that was generated by the include operation.

The error-page configuration in web.xml looks like:

 <error-page>     <exception-type>         javax.servlet.ServletException     </exception-type>     <location>/error</location> </error-page> 

where "/error" is mapped to a servlet that displays exception- related information.

In Example 6-7, the context path was empty and the servlet path was /level2 . Figure 6-4 shows a browser displaying the error page. The servlet generating the exception is specified as the top-level servlet ( MultipleInc ) because this was the code that originated the include mechanism which resulted in the ServletException .

Figure 6-4. Displaying exception information caused during an include operation

Example 6-8 shows the JSP file ( level3.jsp ) that the first inner servlet imports. The level3.jsp file represents the second level of included content.

The included servlets do not call the ) method, because that action would prevent the response that follows the outer servlet's include code from being sent to the client. The outer servlet ( MultipleInc in Example 6-6) finally calls PrintWriter.close( ) when it is finished including the nested resources.

Example 6-8. The included level3.jsp JSP file
 <%@page errorPage="/error"%> <h3>Hello from Level 3</h3> This text is included at Level 3.  <jsp:include page="/level4"/>  

Finally, the JSP file uses the jsp:include standard action to import the text returned from a servlet that is mapped to the /level4 path. The Level4 servlet does the same thing as the other of the recipe's servlets ”it writes character data to the PrintWriter object ”so I have not shown its source code. The reason I included was to demonstrate how several different resource types can be nested in a chain of included files. The outer servlet includes servlet two, which includes a JSP file, which in turn includes the text returned from a third servlet. The first included servlet enclosed its own include code in a try block to catch any exceptions raised by including a JSP file.

See Also

Recipe 6.1 on using the RequestDispatcher include mechanism; Recipe 6.2 on determining an included resource with an configuration file; Recipe 6.4-Recipe 6.8 on including resources in JSPs; Chapter SRV.14.2.5 of the Servlet Recipe 2.4 proposed final specification; Chapter JSP.1.10.3 of the JSP 2.0 specification on including files in JSPs; Chapter 9 on specifying errors pages in web applications.

Java Servlet & JSP Cookbook
Java Servlet & JSP Cookbook
ISBN: 0596005725
EAN: 2147483647
Year: 2004
Pages: 326

Similar book on Amazon © 2008-2017.
If you may any questions please contact us: