Including content

You can include content into your servlets using the following techniques:

For more information on using the RequestDispatcher object, see "Passing control".

Using the include method

You can use the RequestDispatcher object's include method to include multiple types of content in your servlet:

When you use the include method, the calling servlet can write to ServletOutputStream or PrintWriter objects before and after calling the include method. If necessary, you can pass information to the target servlet or JSP using the ServletRequest object's setAttribute method, as described in "Passing control", or using session objects, as described in "Working with sessions".

The following example includes a servlet:

...
PrintWriter out = resp.getWriter();
ServletContext sc = this.getServletContext();
RequestDispatcher rd = sc.getRequestDispatcher("/servlet/includeMe");
if (rd !=null) {
  try {
    // Note- the included servlet has control over its own buffer only.
    rd.include(req, resp);
  }
  catch (Exception e) {
    sc.log("Problem invoking servlet.", e);
  }
}
...

To see a sample servlet, start the samples JRun server and open a browser to http://localhost:8200/techniques.

Using the getResource method

You can use the ServletContext object's getResource method to include content in your servlet. The getResource method returns a URL object. Then you can use the URL object to access the content. One advantage of using the URL object is that you can parse the content before returning it to the browser. You can also use this technique to include content that is otherwise not accessible to the users directly, such as files in the /WEB-INF directory.

The following example includes content using the getResource method:

...
resp.setContentType("text/html");
ServletOutputStream out = resp.getOutputStream();
ServletContext sc = this.getServletContext();
try {
  URL u = sc.getResource("/includedText.htm");
  if (u !=null) {
    // Access the content, casting to an InputStream
    InputStream in = (InputStream)u.getContent();
    byte[] buf = new byte[255];
    int numRead = in.read(buf);
    while(numRead != -1){
      out.write(buf, 0, numRead);
      numRead = in.read(buf);
    }
  }else {
    out.println("<p>u was null");
  }
} catch (Exception e) {}
...

Getting content from other HTML pages

J2EE makes it easy to get web pages from the Internet, parse those pages, and include the content in your own pages. Common applications of this technique are to add box scores or stock ticker symbols price quotes to your own pages to provide dynamic data.

The target website must output regular data that you can parse using known string. Regular data means that each piece falls within a set of delimiters. To get price information, for example, the price of a product must be represented the same way with the same HTML tags surrounding it on the target page for all of your harvesting calls to work.

For example, the website www.funagain.com generates dynamic pages using a game ID. Funagain generates a page that lists a number of attributes such as price, designer, and manufacturer for each game. These attributes are represented in the HTML of the Funagain web pages as hidden form fields, as the following example shows:

<INPUT TYPE="HIDDEN" NAME="manufacturer" VALUE="Amigo">

In this example, the HTML page that shows a game's details at Funagain contains a hidden form field that defines the manufacturer. Funagain generates a page with the same regularity for all games. In the same manner, finance.yahoo.com generates page with the same data format for stock quotes.

You can use the technique in this section to extract the value of the manufacturer hidden form field.

To include dynamic content from other pages in your application:

  1. Build a URL. In this example, the URL consists of the base Funagain URL, plus the game ID that you enter in the form field. The following example shows building a target URL:
    ...
    String gameID = request.getParameter("gameID");
    String urlString = "http://kumquat.com/cgi-kumquat/funagain/" + gameID;
    ...
    funagainURL = new URL(urlString);
    ...
    
  2. Open a URL Connection to the target website, as the following line shows:
    funagainConnection = funagainURL.openConnection();
    
  3. Get an InputStream from the new connection, as the following example shows:
    webPageInputStream = funagainConnection.getInputStream();
    
  4. Read the target InputStream into a buffer, as the following example shows:
    ...
    StringBuffer webPageDataBuffer = new StringBuffer(32000);
    int totalBytesRead = 0;
    boolean moreToRead = true;
    byte[] readBuf = new byte[4096]; // Read the web page in 4K chunks
    while (moreToRead) {
      int numBytesRead = 0;
      try {
        numBytesRead = webPageInputStream.read(readBuf);
      } catch (IOException e) {
        moreToRead = false;
        numBytesRead = -1;
      }
      if (numBytesRead > 0) {
        totalBytesRead += numBytesRead;
        webPageDataBuffer.append(new String(readBuf, 0, numBytesRead));
      } else {
        moreToRead = false;
      }
    }
    ...
    webpageDataBuffer.setLength(totalBytesRead);
    ...
    
  5. Convert the web page buffer to a String, as the following line shows:
    String webPageData = webPageDataBuffer.toString();
    
  6. Establish the delimiters for the target data you want to extract, as the following example shows:
    label[3] = "Year: ";
    predetails[3] = "year\" VALUE=\"";
    postdetails[3] = "\">";
    

    This example searches for the occurrence of the following String as the starting delimiter:

    year" VALUE="

    The example searches for \"> and sets that as an ending delimiter.

    The following line from the target website matches the search:

    <INPUT TYPE="HIDDEN" NAME="year" VALUE="1999">

    The 1999 is delimited by the predetails and postdetails delimiters.

  7. Parse the String representation of the web page, searching for Strings that match the delimiters, as the following example shows:
    ...
    int preStringLoc;
    int postStringLoc;
    preStringLoc = WebPageData.indexOf(predetails[i]);
    postStringLoc = WebPageData.indexOf(postdetails[i], preStringLoc);
    if (preStringLoc == -1 || postStringLoc == -1) {
      details[i] = "N/A";
    } else {
      details[i] = WebPageData.substring(preStringLoc + predetails[i].length(), postStringLoc);
    }
    ...
    
  8. Print the targeted data that matches the delimiters, as the following example shows:
    ...
    for (int i = 0; i < details.length; i++) {
      out.println(label[i] + details[i]);
      out.println("<BR>");
    }
    ...
    

To see a sample servlet, start the samples JRun server and open a browser to http://localhost:8200/techniques.