Transcript Servlet
CSC 2720
Building Web Applications
Java Servlet (Part 2)
Thread-Safe Servlet
Sending Error Messages
Request Dispatching
Thread-Safe Servlet
Multi-threaded Servlets
Regardless of the number of requests to the same servlet,
a server container creates only one instance of the servlet.
To handle multiple requests to the same servlet, a server
container creates multiple threads in which each thread
invokes the service() method of the servlet to handle the
request.
Each servlet receives a distinct copy of the “request” and
the “response” objects.
Instance variables of a servlet are shared.
import java.io.*;
import javax.servlet.*;
public class SomeServlet extends GenericServlet {
int instanceVar; // shared by all instances of this servlet
…
public void service(ServletRequest request,
ServletResponse response)
throws ServletException, IOException
{ … }
}
Thread 1
ServletRequest request;
ServletResponse response;
run() {
…
}
Thread 2
ServletRequest request;
ServletResponse response;
run() {
…
}
SomeServlet Object
int instanceVar;
service(…) { … }
Servlet Container
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.io.*;
import javax.servlet.*;
public class UnsafeCounterServlet extends GenericServlet {
public void service(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
// 1. Read the counter from a file
// 2. Increment counter
// 3. Write the counter to a file
}
}
Multi-threaded servlets become unsafe when they need to
share resources such as instance variables, files, and
database.
Demo: A servlet that increments a value stored in a file
Thread-Unsafe Servlet Demo
UnsafeCounterServlet (Thread 1)
UnsafeCounterServlet (Thread 2)
doGet() {
// 1. Read counter
// 2. Increment counter
// 3. Write counter
}
doGet() {
// 1. Read counter
// 2. Increment counter
// 3. Write counter
}
1. Server receives two requests to UnsafeCounterServlet
2. Server creates two threads to handle the requests. Each
thread takes turn to run.
Assuming the value stored in the file is 0.
Thread-Unsafe Servlet Demo
UnsafeCounterServlet (Thread 1)
UnsafeCounterServlet (Thread 2)
doGet() {
// 1. Read counter
// 2. Increment counter
// 3. Write counter
}
doGet() {
// 1. Read counter
// 2. Increment counter
// 3. Write counter
}
1. Thread 1 runs first and manages to finish the first two steps.
Thread-Unsafe Servlet Demo
UnsafeCounterServlet (Thread 1)
UnsafeCounterServlet (Thread 2)
doGet() {
// 1. Read counter
// 2. Increment counter
// 3. Write counter
}
doGet() {
// 1. Read counter
// 2. Increment counter
// 3. Write counter
}
1. Thread 2 is scheduled to run next and also manages to
finish the first two steps.
2. Both threads assign 0 to “counter”.
Thread-Unsafe Servlet Demo
UnsafeCounterServlet (Thread 1)
UnsafeCounterServlet (Thread 2)
doGet() {
// 1. Read counter
// 2. Increment counter
// 3. Write counter
}
doGet() {
// 1. Read counter
// 2. Increment counter
// 3. Write counter
}
1. Both threads eventually complete their tasks.
2. Because both threads read the value 0 from the same file,
the final value written to the file is 1 instead of 2.
3. Create problems when your web application relies on
counting “hits” to generate revenue.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.io.*;
import javax.servlet.*;
public class SafeCounterServlet extends GenericServlet
implements SingleThreadModel {
public void service(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
// 1. Read the counter from a file
// 2. Increment counter
// 3. Write the counter to a file
}
}
One possible solution: Single-threaded servlet
Have the servlet implements the interface SingleThreadModel
No need to add additional methods.
Servlets are scheduled to run sequentially on the first come first
served basis.
What's the drawback? Should all servlets that share resources be
made into single-threaded servlets?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.io.*;
import javax.servlet.*;
public class SafeCounterServlet extends GenericServlet {
int lock;
public void service(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
synchronized (lock) {
// 1. Read the counter from a file
}
// 2. Increment counter
synchronized (lock) {
// 3. Write the counter to a file
}
}
}
Another possible solution:
Use the language feature to write thread safe code
In this example, only one of the read/write operations can be
performed by any thread at any given time.
Sending an Error Code
Sending an Error Code
The HttpServletResponse object in doGet() or
doPost() contains methods to send pre-defined error
code and error message.
void sendError(int sc);
void sendError(int sc, String errorMsg);
sc is a HTTP status code defined as constant in
HttpServletResponse
errorMsg is a customized error message.
e.g.:
response.sendError(HttpServletResponse.SC_FORBIDDEN,
"Login Failed");
SC_FORBIDDEN corresponds to HTTP status code 403
response.sendError(response.SC_NOT_FOUND);
SC_NOT_FOUND corresponds to HTTP status code 404
See HttpServletResponse for a complete list of status code constants
protected void processRequest(
// Method generated by NetBeans
HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.sendError(response.SC_NOT_FOUND,
"Generated by SendErrorDemoServlet");
}
sendError() Demo
You can configure the web server to use customized pages
to convey error messages.
Categories of Status Code
100-199
Indicate the client should respond with some other actions.
200-299
Indicate the request was successful.
300-399
Usually include a location header
400-499
Indicate an error by the client.
500-599
Indicate an error by the server.
See list of HTTP status codes at Wikipedia.
Request Dispatching – Forward and Include
Request Dispatching
To include static or dynamic file content
To pass the processing of an HTTP request from your
servlet to another servlet
RequestDispatcher object
public void include(ServletRequest request,
ServletResponse response)
public void forward(ServletRequest request,
ServletResponse response)
Both methods may throw ServletException and IOException
Obtaining RequestDispatcher object #1
A RequestDispatcher object acts as a wrapper for a
resource corresponds to a specified path.
Call getRequestDispatcher() of ServletContext
object
Path name is relative to the root of the servlet's context and
must start with '/' as prefix
e.g.
String path = "/AnotherServlet";
RequestDispatcher rd =
getServletContext().getRequestDispatcher(path);
Obtaining RequestDispatcher object #2
Call getRequestDispatcher() of ServletRequest
object
String path = "AnotherServlet";
// Suppose AnotherServlet is located in the same
// directory as the current servlet
RequestDispatcher rd =
request.getRequestDispatcher(path);
With this method, the path name is relative to the location of
the current servlet.
Don’t use '/' as prefix because it indicates the path name
that follows is relative to the root of the ServletContext.
Obtaining RequestDispatcher object #3
Call getNamedDispatcher() of ServletContext
object
String servletName = "AnotherServlet";
// Suppose AnotherServlet is located in the same
// directory of the current servlet
RequestDispatcher rd =
getServletContext.getNamedDispatcher(servletName);
servletName is a name assigned to the servlet or JSP
page and is defined in web.xml.
Including Other Resources
protected void processRequest(
// Method generated by NetBeans
HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
// Can use "out" to write something here
RequestDispatcher rd =
getServletContext().getRequestDispatcher("index.jsp");
rd.include(request, response);
// Con use "out" to write something here
}
If the included resource is a Java Servlet, the included servlet can only write
to the PrintWriter object of the response object, and cannot modify the
header info of the response object.
One can include as many resources as one need.
Forwarding Processing Control
protected void processRequest(
// Method generated by NetBeans
HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Cannot flush output here
RequestDispatcher rd =
getServletContext().getRequestDispatcher("index.jsp");
rd.forward(request, response);
// Cannot write to the PrintWriter object
// or modify the response's header info
}
If you have written something to the PrintWriter object prior to
calling "rd.forward()", you may call "response.reset()"
to clear the output.
sendRedirect()
The method sendRedirect() of
HttpServletResponse object can also be used to
redirect the client to a different resource.
String path = "AnotherServlet";
// Suppose AnotherServlet is located in the same
// directory of the current servlet
response.sendRedirect(path);
path can also be a string representing an absolute URL.
sendRedirect() "asks" the client to request a different
resource whereas forward() passes another resource to
the client.
Summary
Reference:
"Java for the Web with Servlets, JSP, and EJB" by Budi
Kurniawan