In many cases, one servlet processes form data, then
transfers control to another servlet or JSP to do some more processing
or display a confirmation message on the screen. There are two ways of
doing this: either the request can be forwarded or the response can be
redirected to another servlet or page.
Request forwarding
Notice how the text displayed in the previous section's example matches the value of the value
attribute of the checkboxes that were clicked, and not the labels
displayed on the previous page. This might confuse the users. Let's
modify the servlet to change these values so that they match the labels,
then forward the request to another servlet that will display the
confirmation message on the browser.
The new version of MultipleValueFieldHandlerServlet is shown in the following code:
package net.ensode.glassfishbook.formhandling;
import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MultipleValueFieldHandlerServlet extends HttpServlet
{
protected void doPost(HttpServletRequest request, HttpServletResponse response)
{
String[] selectedOptions = request.getParameterValues("options");
ArrayList<String> selectedOptionLabels = null;
if (selectedOptions != null)
{
selectedOptionLabels = new ArrayList<String>(selectedOptions.length);
for (String selectedOption : selectedOptions)
{
if (selectedOption.equals("option1"))
{
selectedOptionLabels.add("Option 1");
}
else if (selectedOption.equals("option2"))
{
selectedOptionLabels.add("Option 2");
}
else if (selectedOption.equals("option3"))
{
selectedOptionLabels.add("Option 3");
}
}
}
request.setAttribute("checkedLabels", selectedOptionLabels);
try
{
request.getRequestDispatcher("confirmation servlet").forward(request, response);
}
catch (ServletException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
This version of the servlet iterates through the selected options and adds the corresponding label to an ArrayList of strings. This string is then attached to the request object by calling the request.setAttribute()
method. This method is used to attach any object to the request so
that any other code we forward the request to can have access to it
later.
After attaching the ArrayList to the request, we then forward the request to the new servlet using the following line of code:
request.getRequestDispatcher("confirmationservlet").forward(
request, response);
The String argument to this method must match the value of the<url-pattern> tag of the servlet in the application's web.xml file.
At this point, control goes to our new servlet. The code for this new servlet is as follows:
package net.ensode.glassfishbook.requestforward;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ConfirmationServlet extends HttpServlet
{
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
{
try
{
PrintWriter printWriter;
List<String> checkedLabels = (List<String>) request.getAttribute("checkedLabels");
response.setContentType("text/html");
printWriter = response.getWriter();
printWriter.println("<p>");
printWriter.print("The following options were selected:");
printWriter.println("<br/>");
if (checkedLabels != null)
{
for (String optionLabel : checkedLabels)
{
printWriter.print(optionLabel);
printWriter.println("<br/>");
}
}
else
{
printWriter.println("None");
}
printWriter.println("</p>");
}
catch (IOException ioException)
{
ioException.printStackTrace();
}
}
}
This code obtains the ArrayList that was attached to the request by the previous servlet. This is accomplished by calling the request.getAttribute() method. The parameter for this method must match the value used to attach the object to the request.
Once the previous servlet obtains a list of option labels, it traverses through it and displays them on the browser:
Forwarding a request
as described before works only for other resources (servlets and JSP
pages) in the same context as the code doing the forwarding. In simple
terms, the servlet or JSP we want to forward to must be packaged in the
same WAR file as the code invoking the request.getRequestDispatcher().forward()
method. If we need to direct the user to a page in another context (or
even another server), we can do it by redirecting the response object.
Response redirection
One disadvantage of
forwarding a request as described in the previous section is that
requests can only be forwarded to other servlets or JSPs in the same
context. If we need to direct the user to a page on a different context
(deployed in another WAR file in the same server or deployed in a
different server), we need to use the HttpServletResponse.sendRedirect() method.
To illustrate response
redirection, let's develop a simple web application that asks the user
to select their favorite search engine, then directs the user to his/her
search engine of choice. The HTML page for this application would look
as follows:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Response Redirection Demo</title>
</head>
<body>
<form method="post" action="responseredirectionservlet">
Please indicate your favorite search engine.
<table>
<tr>
<td><input type="radio" name="searchEngine" value="http://www.google.com">Google</td>
</tr>
<tr>
<td><input type="radio" name="searchEngine" value="http://www.msn.com">MSN</td>
</tr>
<tr>
<td><input type="radio" name="searchEngine" value="http://www.yahoo.com">Yahoo!</td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Submit" /></td>
</tr>
</table>
</form>
</body>
</html>
The HTML form in this
markup code contains three radio buttons. The value for each of them is
the URL for the search engine corresponding to the user's selection.
Notice how the value for the name attribute of each radio button is the same, namely searchEngine. The servlet will obtain the value of the selected radio button by calling the request.getParameter() method and passing the string searchEngine as a parameter. This is demonstrated in the following code:
package net.ensode.glassfishbook.responseredirection;
response redirectionillustratingimport java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ResponseRedirectionServlet extends HttpServlet
{
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException
{
String url = request.getParameter("searchEngine");
if (url != null)
{
response.sendRedirect(url);
}
else
{
PrintWriter printWriter = response.getWriter();
printWriter.println("No search engine was selected.");
}
}
}
By calling request.getParameter("searchEngine"), the previous code assigns the URL of the selected search engine to the variable url. Then (after checking for null,
in case the user clicked on the submit button without selecting a
search engine), directs the user to the selected search engine by
calling response.sendRedirect() and passing the url variable as a parameter.
The web.xml file for this application should be fairly straightforward and is not shown .
After packaging the code and deploying it, we can see it in action by typing the following URL in the browser: http://localhost:8080/responseredirection/.
After clicking on the Submit button, the user is directed to their favorite search engine.
It should be noted that
redirecting the response as just illustrated creates a new HTTP request
to the page we are redirecting to. Therefore, any request parameters and
attributes are lost.