Saturday, February 14, 2009

Calling other Servlets or other resources

Calling other Servlets or other resources
using a RequestDispatcher
('include' and 'forward')

To have your servlet access another resource, such as another servlet, a JSP page or a CGI script, you can either:

* Have the servlet make an HTTP request (this is a general Java programming language skill).

* Make a request for the resource using a RequestDispatcher object, if the resource is available from the server that is running the servlet.

To gain access to a RequestDispatcher object, use the ServletContext object's getRequestDispatcher() method. The getServletContext() method should be called on the ServletConfig reference (config) stored during the servlet's init() method:

config.getServletContext().getRequestDispatcher(url)

The getRequestDispatcher method takes the requested resource's relative URL as an argument. The format of this argument is a slash ("/") followed by one or more slash-separated directory names, and ending with the name of the resource. The URL must be for a resource currently available on the server that is running the servlet. If the resource is not available, or if the server has not implemented a RequestDispatcher object for that type of resource, this method will return null. The Kinabaloo Web Server can handle all the main resource types, such as HTML and JSP pages, and other servlets.



Forwarding a Request

Once you have the RequestDispatcher object, you can pass the responsibility for responding to the client request to another resource. Forwarding is useful, for example, when the servlet processes the request but the response is generic so it can be handed off to another resource.

A servlet might, for example, handle a user's credit card information when a user places an order, then pass the client request to another servlet that returns a "Thank you" page. In the Duke's Bookstore example, BookStoreServlet gets (creates if necessary) the user session, then has the request dispatcher return the front page of the bookstore:

public class BookStoreServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// Get the dispatcher; it will send the main page to the user

RequestDispatcher dispatcher = config.getServletContext().getRequestDispatcher("/bookstore.html");

if (dispatcher == null) {

// No dispatcher means the resource (bookstore.html in this case) can not be found

response.sendError(response.SC_NO_CONTENT);

} else {

// Send the user the bookstore's opening page

dispatcher.forward(request, response);

}

...



Note that the ServletConfig object config was obtained during the init(ServletConfig config) method of the servlet.

Remember that the forward method should be used to give another resource full responsibility for replying to the user. If you have already accessed a ServletOutputStream or PrintWriter object, you cannot use this method - it will throw an IllegalStateException in these circumstances.

If you have already started replying to the user by accessing a PrintWriter or ServletOutputStream, you must use the include method instead.



Including a Request

The include(URL) method of the RequestDispatcher interface allows the calling servlet to respond to the client, and also allows another resource to send part of the reply. The servlet can use the PrintWriter and ServletOutputStream objects both before and after calling the include method.

You must keep in mind, however, that the called (included) resource should not try to set any http headers in the client response (if the resource tries to set headers, the headers are not guaranteed to be set).

The following example shows what a ReceiptServlet might look like if, instead of merely thanking the user for the order, it also included an order-summary. The following example thanks the user for the order, then includes the output of an order summary servlet in the output:

public class ReceiptServlet extends HttpServlet {

public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

// Process a customer's order

...

// Thank the customer for the order

res.setContentType("text/html");

PrintWriter toClient = res.getWriter();

toClient.println("");

toClient.println("

Thank you for your order!

");

// Get the request-dispatcher, to send an order-summary to the client

// (OrderSummary is a servlet)

RequestDispatcher summary = config.getServletContext().getRequestDispatcher("/OrderSummary");

// Have the servlet summarize the order. Skip summary on error.

if (summary != null) {

try {

summary.include(req, res);

} catch (Exception e) {...}

}

// and finish the response page :

toClient.println("

Come back soon!

");

toClient.println("");

toClient.close();

}

}

No comments: