Servlet-Container Communication

 < Free Open Study > 



The servlet container is responsible for managing, creating and destroying servlets in our web application. Therefore the container needs a way to communicate with the servlet and vice-versa.

The servlet container uses objects that implement specific interfaces to pass information into the servlet (such as initialization parameters), and to pass in information about the container or context that the servlet is being executed in.

These are implemented as interfaces because the interface defines the contract between the objects passed to the servlet and the servlet itself. However the specific implementation of the interface is the responsibility of the servlet container, and the container may incorporate other features customized to the container. The servlet is given access to the specific methods defined by the interfaces.

The ServletConfig interface is used by the servlet container to create an object that contains information that may be required to configure the servlet. It contains any servlet initialization parameters, the servlet's name (as known to the container) and has a ServletContext object. The ServletConfig object is passed to the init() method of the servlet which then stores a reference to this object and, if required, extracts information required to initialize the servlet.

The container constructs the ServletContext interface object to hold information about the servlet and container environment (such as the server name and version, attributes, and so on). The ServletConfig object contains methods to access the ServletContext object, and vice versa.

ServletContext lifecycle events, such as changes to the ServletContext object or the ServletContext attributes, generate ServletContextEvent and ServletContextAttributeEvent objects. We can develop listener classes to listen for these events, implementing the ServletContextListener interface and the ServletContextAttributeListener interface respectively.

Implementing ContainerServlet

As we discuss the ServletConfig and ServletContext interfaces, we will implement an example ContainerServlet that will use many of the methods we will discuss.

The ContainerServlet class extends the GenericServlet class to provide a basic servlet that demonstrates the use of the ServletConfig and ServletContext objects, and returns the data to the client in HTML format. The servlet outputs a table of ServletConfig and ServletContext parameters, making use of the simple HTMLTable utility class that that we developed in the previous example (RequestResponseServlet):

click to expand

As with the previous example, if you wish to run the example yourself, you will need to place the source code files in the basicServlets directory, compile them from the src directory, and then move the Java class files created to the classes\basicServlets directory.

You can access the servlet on the following URL:

http://localhost:8080/servletAPI/servlet/basicServlets.ContainerServlet

The ContainerServlet

The ContainerServlet example shows how we can retrieve information from the ServletConfig and ServletContext objects provided by the servlet container. Let's take a look at the source code:

    package basicServlets;    import javax.servlet.*;    import javax.servlet.http.*;    import java.io.*;    import java.util.*;    public class ContainerServlet extends GenericServlet { 

The ContainerServlet class is very similar to the previous RequestResponseServlet class. We have implemented the service() method to process requests. We have two methods to build HTML tables, but in this case the tables contain information about the ServletConfig and ServletContext objects created by the servlet container:

      public void service(ServletRequest request, ServletResponse response)        throws ServletException, IOException {        StringBuffer configTable = getConfigTable(getServletConfig());        StringBuffer contextTable = getContextTable(getServletContext());        response.setContentType("text/html");        PrintWriter out = response.getWriter();        //HTML page        out.println("<html><head><title>ContainerServlet</title></head><body>");        out.println("<h1>Config Information</h1>" + configTable + "<hr>");        out.println("<h1>Context Information</h1>" + contextTable);        out.println("</body></html>");        out.close();      } 

As we look at the methods available in the ServletConfig and ServletContext interfaces, we will build up the getConfigTable() and getContextTable() methods that give examples of how to use the interface methods.

The ServletConfig Interface

The ServletConfig interface is implemented by the GenericServlet class, so you should not be surprised to find that every method in this interface is implemented (with others) in the GenericServlet class. In fact, when you call a method on the GenericServlet class that is specified by the interface, the GenericServlet class calls the same method on the ServletConfig object passed to it (by the servlet container) in the init() method. The GenericServlet class implements this interface as a convenience, so that we do not have to directly reference the ServletConfig object every time we call the method. This means that the method calls in our example should be relatively straightforward, and analogous to the some of the methods called on the BasicServlet example.

Retrieving Information from ServletConfig

We do not necessarily need to know the servlet initialization parameter names at development time (although usually we would). We can use the getInitParameterNames() method to return an Enumeration of the parameter names that we can iterate though to extract the corresponding values:

    public java.util.Enumeration getInitParameterNames() 

The getInitParameter() method is used to extract the initialization parameter values set for the servlet:

    public String getInitParameter(String name) 

The following method returns a reference to the ServletContext object:

    public ServletContext getServletContext() 

The following section details the methods that may be used on objects of this type. The servlet container knows each servlet by a specific name (this is normally set in the deployment descriptor file, see Chapter 4 for more information). This name can be retrieved by the getServletName() method (essentially the same as the GenericServlet.getServletName() method):

    public String getServletName() 

Using ServletConfig in getConfigTable()

The getConfigTable() method takes a reference to the ServletConfig object and returns an HTML table with information from the ServletConfig object. Strictly speaking, since this method is declared within the servlet we do not have to pass the ServletConfig object in as a parameter, because we could just call the getServletConfig() method to get a reference to it. However this is included as a parameter because we could then refactor this method (and any additional methods) into a separate class, if required, without modification:

      private StringBuffer getConfigTable(ServletConfig config) {        HTMLTable table = new HTMLTable(); 

We add the servlet name to the table, followed by the initialization parameters (if any). In this case we have not configured any for this servlet. We will explain how to add initialization parameters in Chapter 4:

        table.appendRow("Servlet Name", config.getServletName());        Enumeration e = config.getInitParameterNames();        while (e.hasMoreElements()) {          String paramName = (String)e.nextElement();          String paramValue = config.getInitParameter(paramName);          table.appendRow("Parameter: <code>" + paramName +                          "</code>", paramValue);        }        return table.toStringBuffer();      } 

Since we haven't added any initialization parameters, the Config Information table only shows the servlet name:

click to expand

The ServletContext Interface

The ServletContext object contains information about the servlet and container environment. The servlet container can give the servlet additional information not already provided by this interface by adding an attribute object to the ServletContext.

Accessing ServletContext Attributes

Four methods exist to access attributes attached to the ServletContext. This method is used to return an Enumeration of the attribute names:

    public java.util.Enumeration getAttributeNames() 

Calling the getAttribute() method with a specified attribute name returns a reference to the requested attribute (or null if the attribute specified does not exist):

    public Object getAttribute(String name) 

Calling the removeAttribute() method will remove the specified attribute (if it exists) from the ServletContext:

    public void removeAttribute(String name) 

Calling the setAttribute() method with a name and Object stores the Object (as an attribute), bound to the specified name:

    public void setAttribute(String name, Object object) 

Using ServletContext Attributes in getContextTable()

The getContextTable() method takes a reference to the servlet's ServletContext object and returns a HTML table (in a StringBuffer object) with information from the ServletContext object. Similar to the previous method, we could access the servlet's ServletContext object using the getServletContext() method of the GenericServlet (we do not necessarily need to pass it as a parameter). However we have included it as a parameter, in case we wanted to reuse this method for other servlets. If we were to do so, we would abstract the method into a separate class.

      private StringBuffer getContextTable(ServletContext context) {        HTMLTable table = new HTMLTable();        table.appendTitleRow("Attributes"); 

Here we will iterate through the attributes set by the servlet container. Since the attributes may be any type derived from Object, we check their type, printing the Object.toString() value if they are not String or String arrays:

        Enumeration e = context.getAttributeNames();        while (e.hasMoreElements()) {          String paramName = (String)e.nextElement();          Object paramObject = context.getAttribute(paramName);          String paramValue = "";          if (paramObject instanceof String) {            paramValue = (String)context.getAttribute(paramName);          } else if (paramObject instanceof String[]) {            String[] paramArray = (String[])context.getAttribute(paramName);            for (int i = 0; i < paramArray.length; i++) {              paramValue = paramValue + paramArray[i] + "<br>";            }          }          else {            paramValue = context.getAttribute(paramName).toString();          }          table.appendRow("Attribute: <code>" + paramName +                          "</code>", paramValue);        } 

Obtaining General Servlet Information

The following methods return information about the servlet and its initialization parameters. The first method returns an Enumeration of the parameter names, while the second returns the requested parameter (or null if it does not exist):

    public java.util.Enumeration getInitParameterNames()    public String getInitParameter(String name) 

The getServletContextName() method will return the name of this web application as known to the servlet container:

    public String getServletContextName() 

Retrieving General Servlet Information in getContextTable()

To extract information about the servlet we begin with the web application's name, as it is known to the servlet container. We then add any initialization parameters to the table:

        table.appendTitleRow("Servlet Information");        table.appendRow("Web App Name", context.getServletContextName());        Enumeration enum = context.getInitParameterNames();        while (enum.hasMoreElements()) {          String paramName = (String)enum.nextElement();          String paramValue = context.getInitParameter(paramName);          table.appendRow("Parameter: <code>" + paramName + "</code>",                           paramValue);        } 

However, since we have not configured any initialization parameters, they will not be displayed. If you wish to set up initialization parameters for this servlet, in order to test this functionality, you should refer to Chapter 4 where we discuss the subject further.

Getting Server Information

Three methods also exist to access information about the server on which the web application/servlet is running. These two methods return the major and minor versions of the Servlet API respectively:

    public int getMajorVersion()    public int getMinorVersion() 

The following method returns the name and version of the servlet container in which the servlet is running:

    public String getServerInfo() 

Getting Server Information in getContextTable()

We can access the version of the Servlet API supported as shown, and the server's information and version also. This is useful for servlets and web applications that may be deployed on different servers and need a particular version of the Servlet API, such as 2.3 or later, to function:

        table.appendTitleRow("Server Information");        table.appendRow("Servlet API version",                  context.getMajorVersion() + "." + context.getMinorVersion());        table.appendRow("Server Version", context.getServerInfo()); 

Getting Information About the Server Environment

Additional methods exist to interact locally with the servlet environment. Calling the getContext() method will return a reference to the ServletContext object for that relative path (null if it does not exist):

    public ServletContext getContext(String uripath) 

Two methods exist to access a RequestDispatcher object that acts as a wrapper for a servlet or specified resource:

    public RequestDispatcher getNamedDispatcher(String name)    public RequestDispatcher getRequestDispatcher(String path) 

We use the first method to access a specific RequestDispatcher object for a specified servlet name. The second method is used to access a specific RequestDispatcher object for a specified resource (at the given path). This second method can take the path to a servlet or file, and can be used to include, or forward, a request to a servlet or static file.

Passing the getRealPath() method a virtual path returns a real file path to this resource on the current server:

    public String getRealPath(String path) 

This is the local file location such as "c:\Apache Tomcat 4.0\webapps\servletAPI\index.html" or "/apps/tomcat/webapps/servletAPI/index.html" that is represented by the virtual path supplied, such as "/index.html".

The getResourcePaths() method will return a Set, analogous to a directory listing, of all the paths to resources within the web application, whose longest sub-path matched the parameter:

    public java.util.Set getResourcePaths(String path) 

The getResource() method returns a URL object that maps to the specified path. This must be a valid path within the current application context, such as "/index.html":

    public java.net.URL getResource(String path) 

Calling the getResourceAsStream() method returns an InputStream object that can be used to read the specified resource. This InputStream object can be wrapped in a suitable input object to interpret the resource (for instance: text, serialized Java objects, a binary or other file):

    public java.io.InputStream getResourceAsStream(String path) 

Finally, with the getMimeType() method we can (attempt to) identify the MIME type of the specified file. This method returns null if the MIME type of this file is not recognized:

    public String getMimeType(String file) 

Getting Server Environment Information in getContextTable()

To complete the getContextTable() method, we are going to look at how we can begin to access the server environment, such as local files:

        table.appendTitleRow("Server Environment");        table.appendRow("Real Path (<code>\"/\"<code>)",                         context.getRealPath("/")); 

First we add the real path (file location) corresponding to a location in our application. Next we will retrieve a Set of resource paths for the relative location specified. Here we are looking for the listing of our root directory. We will then append the paths to a StringBuffer and add this row to the table:

        Set setPaths = context.getResourcePaths("/");        Object[] arrayPaths = setPaths.toArray();        StringBuffer bufferPaths = new StringBuffer();        for (int i = 0; i < arrayPaths.length; i++) {          bufferPaths.append((String)arrayPaths[i]).append("<br>");        }        table.appendRow("Paths", bufferPaths.toString()); 

Next we retrieve a URL object for the specified index.html page. This URL object could be used to retrieve the object, if required, but here we add its location to the table. If there is a problem, we output an indication that this returned a null URL:

        try {          URL url = context.getResource("/index.html");          if (url != null) {            table.appendRow("URL (<code>\"/index.html\"<code>)",                             url.toString());          } else {            table.appendRow("URL (<code>\"/index.html\"<code>)", "null");          }        } catch (MalformedURLException mfe) {          table.appendRow("MalformedURLException (<code>\"/index.html\"<code>)",                          mfe.getMessage());        } 

Finally we determine the MIME type for the index.html page. In Tomcat, this maps the extension to its MIME type, if known. It does not validate that the file exists:

        table.appendRow("Mime Type (<code>\"index.html\"<code>)",                         context.getMimeType("index.html"));        return table.toStringBuffer();      }    } 

Finally, the table is then returned by the method. Here's a reminder of what it looks like in the browser:

click to expand

Utility Methods

A couple of log() methods (similar to those in GenericServlet) are provided to write to the web applications log file too:

    public void log(String msg)    public void log(String message, java.lang.Throwable throwable) 

The ServletContext Lifecycle Classes

Modifications to the ServletContext object, such as the initialisation or destruction of it by the servlet container, trigger ServletContextEvent objects. If our application needs to monitor updates to the context in which the servlet is running, we create a class that implements the ServletContextListener interface, and register it with the servlet container (in the application's web.xml deployment descriptor configuration file - Chapter 4 explains this process). A listener class method is executed when a ServletContextEvent event occurs.

Similarly, modifications to ServletContext attributes trigger ServletContextAttributeEvent objects. We can create classes that implement the ServletContextAttributeListener interface to listen for these events too.

The servlet container notifies the registered classes about the events that they are listening for. It is the containers responsibility to then call the relevant method, defined in the listener interface implemented, to process the event. If the events being listened for never occur, then the servlet container does not call the listener methods.

The ServletContextEvent Class

The ServletContextEvent object is passed to the relevant listeners for this event. This has a single method. Calling the getServletContext() method returns the ServletContext object that was modified:

    public ServletContext getServletContext() 

The ServletContextAttributeEvent Class

The ServletContextAttributeEvent object is generated by servlet container when the attributes of a particular ServletContext are altered. This class has two methods. The first returns the name of the attribute changed, and the second the value of the attribute that was altered:

    public String getName()    public Object getValue() 

The returned Object from the getValue() method depends upon the triggering event. If the attribute was added or removed, the added or removed attribute is returned. Alternately, if the attribute was replaced, then the old value of the attribute is returned, allowing it to be saved if required.

The ServletContextListener Interface

We implement the ServletContextListener interface to listen for lifecycle events (initialization or destruction) of the servlet context. We implement the methods below to allow our application to react appropriately to these events:

    public void contextInitialized(ServletContextEvent sce)    public void contextDestroyed(ServletContextEvent sce) 

These methods are called by the servlet container, in response the initialization or the pre-shutdown of the ServletContext.

The ServletContextAttributeListener Interface

The ServletContextAttributeListener interface is implemented by classes to listen for changes to attributes in the ServletContext object. Three methods are provided, corresponding to the three types of action that may trigger the ServletContextAttributeEvent. It is the servlet container's responsibility to call these methods once the event trigger occurs:

    public void attributeAdded(ServletContextAttributeEvent scab)    public void attributeRemoved(ServletContextAttributeEvent scab)    public void attributeReplaced(ServletContextAttributeEvent scab) 

We implement these methods to process the addition, removal and replacement of attributes respectively.



 < Free Open Study > 



Professional Java Servlets 2.3
Professional Java Servlets 2.3
ISBN: 186100561X
EAN: 2147483647
Year: 2006
Pages: 130

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net