3. The Servlet Environment
This chapter shows how to access resources of the Web Server
and communicate with Servlets and other kinds of active
resources (e.g. JSP
documents, CGI
programs). The examples in this chapter are
often only fragments of Java source code and not necessarily
complete Servlets.
3.1 Inter-Servlet Communication
This section shows how to
- call a method of another Servlet
|
The inter-Servlet communication method which is described in this section
can only be used with Servlet engines which implement version 1.0 or 2.0
of the Servlet API. It will not work with Servlet engines which comply
strictly to version 2.1. The new way of doing inter-Servlet communication
which was introduced in the 2.1 API is described in detail in sections
3.2 and 3.5.
|
Servlets are not alone in a Web Server. They have access to other
Servlets in the same Servlet Context (usually a Servlet directory),
represented by an instance of javax.servlet.ServletContext.
The ServletContext is available through the
ServletConfig object's getServletContext
method.
A Servlet can get a list of all other Servlets in the Servlet Context
by calling getServletNames on the ServletContext
object. A Servlet for a known name (probably obtained through
getServletNames) is returned by getServlet.
Note that this method can throw a ServletException because
it may need to load and initialize the requested Servlet if this was not
already done.
After obtaining the reference to another Servlet that Servlet's
methods can be called. Methods which are not declared in
javax.servlet.Servlet but in a subclass thereof
can be called by casting the returned object to the required class
type.
Note that in Java the identity of a class is not only defined by the class
name but also by the ClassLoader by which it was loaded. Web
servers usually load each Servlet with a different class loader. This is
necessary to reload Servlets on the fly because single classes
cannot be replaced in the running
JVM.
Only a ClassLoader
object with all loaded classes can be replaced.
This means that classes which are loaded by a Servlet class loader
cannot be used for inter-Servlet communication. A class literal
FooServlet (as used in a type cast like
"FooServlet foo = (FooServlet)context.getServlet("FooServlet")")
which is used in class BarServlet is different from the class
literal FooServlet as used in FooServlet itself.
A way to overcome this problem is using a superclass or an interface which
is loaded by the system loader and thus shared by all Servlets. In a Web
Server which is written in Java those classes are usually located in the
class path (as defined by the CLASSPATH environment variable).
Example. Servlet FooServlet wants to
call the method public void bar() of Servlet
BarServlet. Both Servlets should be reloadable so
the Servlet classes cannot be loaded by the system loader. Instead
we define an interface BarInterface which defines the
callable method and is loaded by the system loader. BarServlet
implements this interface. The Servlets are placed into the Servlet
directory and the interface into a directory in the class path.
1: public class FooServlet extends HttpServlet
2: {
3: protected void doGet(HttpServletRequest req,
4: HttpServletResponse res)
5: throws ServletException, IOException
6: {
7: ...
8: ServletContext context = getServletConfig().getServletContext();
9: BarInterface bar = (BarInterface)context.getServlet("BarServlet");
10: bar.bar();
11: ..
12: }
13:
14: ...
15: }
1: public interface BarInterface
2: {
3: public void bar();
4: }
1: public class BarServlet extends HttpServlet implements BarInterface
2: {
3: public void bar()
4: {
5: System.err.println(""bar() called"");
6: }
7:
8: ...
9: }
|
3.2 Communication with Active Server Resources

This section shows how to
- call another Servlet (or any other kind of active resource) to
process a request
A Servlet can make a request to an active resource on the web server
just like a client can (by requesting a URL). The Servlet API supports
a more direct way of accessing server resources from within a Servlet
which is running in the server than opening a socket connection back
to the server. A Servlet can either hand off a request to a different
resource or include the response which is created by that resource
in its own response. It is also possible to supply user-defined data
when calling an active resource which provides for an elegant way
of doing inter-Servlet communication.
|
See section 3.1
for an inter-Servlet communication method which can be used with
Servlet API versions 1.0 and 2.0.
|
Example. We're building an online shop with an
ItemServlet which takes an argument
item=number and returns a paragraph of HTML text
with a description of the item which is retrieved from a database.
A second Servlet, the PresentationServlet, takes the
same argument and creates a complete HTML page which includes
the output of the ItemServlet. If the item
argument is missing, the request is delegated to an
ErrorServlet which returns a formatted error message.
public class PresentationServlet extends HttpServlet
{
private static class ItemNotFoundException extends Exception
{
ItemNotFoundException() { super("Item not found"); }
}
protected void doGet(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException
{
String item = req.getParameter("item");
if(item == null)
{
req.setAttibute("exception", new ItemNotFoundException());
getServletContext()
.getRequestDispatcher("/servlet/ErrorServlet")
.forward(req, res);
}
else
{
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.print("<HTML><HEAD><TITLE>Item " + item + "</TITLE>"+
"</HEAD><BODY>Item " + item + ":<P>");
getServletContext()
.getRequestDispatcher("/servlet/ItemServlet?item="+item)
.include(req, res);
out.print("</BODY></HTML>");
}
}
}
|
In the doGet method we first check for the existence of
the item argument. If it is present (second branch of
the if statement) the Servlet is responding with an HTML
document in the usual way. In the middle of the document the
response body of the ItemServlet is included by asking
the ItemServlet's RequestDispatcher
(whis is obtained through the ServletContext) to
perform that operation.
If no item attribute was specified, the request is
delegated to the ErrorServlet in a similar way.
Note that this time we are using the RequestDispatcher's
forward method (instead of include).
This method can be called only once and only if neither
getOutputStream nor getWriter has
been called, but it allows the included Servlet to set
headers and the response code (which is required to create
a proper HTTP error response message).
The ItemServlet gets its item argument
from the query string. That way it can also be accessed directly
via an HTTP request, but argument values have to be
represented as url-encoded strings (which is no problem in this
case). The ErrorServlet takes an exception
argument of type java.lang.Exception which is provided as a
request attribute. The ErrorServlet uses
the ServletRequest method getAttribute
to read the attribute.
Note that a server which supports load balancing could run the
Servlets on different
JVMs.
All custom request attributes should be serializable to allow
them to be moved from one JVM to another.
3.3 Accessing Passive Server Resources
This section shows how to
- access a resource in the server's document tree
Passive server resources (e.g. static HTML pages which are stored in
local files) are not accessed with RequestDispatcher
objects. The ServletContext method
getResource(String path) returns a URL
object for a resource specified by a local URI (e.g. "/"
for the server's document root) which can be used to examine the
resource.
If you only want to read the resource's body you can directly
ask the ServletContext for an
InputStream with the
getResourceAsStream(String path) method.
In Servlets which have to use version 1.0 or 2.0 of the Servlet API
you can use the ServletContext method
getRealPath(String path) to find a path in the local
file system to a resource. This method is
less general than the one described above because it doesn't allow
you to access resources which are not stored in local files.
|
3.4 Accessing Servlet Resources
This section shows how to
- access resources which belong to a Servlet
A Servlet may need to access additional resources like configuration
files whose locations should not need to be specified in init
parameters. Those resources can be accessed with the methods
getResource(String name) and
getResourceAsStream(String name) of the
java.lang.Class object which represents the Servlet's
class.
Example. The following code gets an
InputStream for a configuration file named
myservlet.cfg which resides in the same
directory as the class in which the code is executed:
InputStream confIn =
getClass().getResourceAsStream("myservlet.cfg");
|
Note that the Servlet engine's Servlet class loader must implement
the getResource and getResourceAsStream
methods in order for this to work. This may not be the case with
all Servlet engines.
3.5 Sharing Data Between Servlets
This section shows how to
- share data between Servlets
Version 2.1 of the Servlet API offers a new way of sharing
named objects between all the Servlets in a
Servlet context (and also other contexts, as you'll
see below) by binding the objects to the ServletContext
object which is shared by several Servlets.
The ServletContext class has several methods for
accessing the shared objects:
-
public void setAttribute(String name,
Object object) adds a new object or replaces an old
object by the specified name. The attribute name should
follow the same naming convention as a package name
(e.g. a Servlet com.foo.fooservlet.FooServlet
could have an attribute com.foo.fooservlet.bar).
Just like a custom ServletRequest attribute,
an object which is stored as a ServletContext attribute
should also be serializable to allow attributes to be shared
by Servlets which are running in different JVMs on
different machines in a load-balancing server environment.
-
public Object getAttribute(String name) returns
the named object or null if the attribute does
not exist.
In addition to the user-defined attributes there
may also be predefined attributes which are specific to the
Servlet engine and provide additional information about a
Servlet(Context)'s environment.
-
public Enumeration getAttributeNames() returns an
Enumeration of the names of all available
attributes.
-
public void removeAttribute(String name) removes the
attribute with the specified name if it exists.
The separation of Servlets into Servlet contexts depends on the
Servlet engine. The ServletContext object of a Servlet
with a known local URI can be retrieved with the method
public ServletContext getContext(String uripath) of
the Servlet's own ServletContext. This method returns
null if there is no Servlet for the specified path
or if this Servlet is not allowed to get the ServletContext
for the specified path due to security restrictions.