Servlet Initialization and Configuration

 < Free Open Study > 



Code can be made more maintainable if properties are not hard coded. File names, network hosts, and database user credentials are all examples of properties that may vary without notice. Rather than hard-coding such values directly into our source code, we should always maintain external configuration repositories outside of the application. The ideal candidate for expressing such configuration data is XML as it provides a data structure that can be easily worked with.

It would be pointless to maintain a separate XML document for simple properties, such as a logging level or the e-mail address of a website manager. For such easily configured properties, the servlet container allows us to set initialization parameters in the application deployment descriptor (web.xml). The deployment descriptor is convenient to use as it is automatically parsed by the servlet container, and the attributes we set are made available through common Java methods.

Initialization parameters and custom XML documents should be used in combination to achieve the best results. For example, it may be best to supply the location of XML configuration files through servlet initialization parameters, rather than hard-coding the file names in the application source code. Such an approach combines the advantages of the two different configuration methods, resulting in the maximum portability and minimum maintenance of our applications.

We will look at these two approaches to custom servlet configuration in more detail. We'll understand:

  • How a servlet can be provided with start-up information through initialization parameters specified at deployment time

  • How to develop a class that can read our XML configuration files

Initialization Parameters

It is useful to be able to supply our servlets with initialization parameters specified in the application deployment descriptor. There are two types of parameters we can set for our servlets:

  • Context-wide parameters are accessible to all servlets within the application (via the associated ServletContext instance)

  • Servlet-specific parameters apply only to a specific servlet

Context-Wide Parameters

Context-wide parameters are set using the <context-param> element in the application deployment descriptor. For example, here we set a parameter named debug with the value false:

    <web-app>      ...        <context-param>          <param-name>debug</param-name>          <param-value>false</param-value>        </context-param>      ...    </web-app> 

Any servlet within the application can access this parameter by using the getInitParameter() method of the application's ServletContext instance. For example, we could retrieve the value of the debug parameter we set above with the following code:

    String str = getServletContext().getInitParameter("debug"); 

If a requested parameter is not set for the application, the getInitParameter() method will return null. This also applies for servlet-specific parameters.

A component in a web application can gain a list of available initialization parameters via the getInitParameterNames() method of ServletContext, which returns an Enumeration of parameter names. For example:

    ServletContext ctx = getServletConfig().getServletContext();    Enumeration e = ctx.getInitParameterNames(); 

Servlet-Specific Parameters

Servlet-specific parameters are set for a specific servlet, through the <init-param> element contained in a <servlet> element in the application's deployment descriptor. For example:

    <web-app>      ...      <servlet>        <servlet-name>MyServlet</servlet-name>        <servlet-class>mypackage.MyServlet</servlet-class>        <init-param>          <param-name>message</paramName>          <param-value>You have reached my servlet!</param-value>        </init-param>      </servlet>      ...    </web-app> 

Each servlet can access its own initialization parameters through the associated ServletConfig instance. For example:

    String message = getServletConfig().getInitParameter("message"); 

As with context-wide parameters, we can obtain an enumeration of available parameters, through the getInitParameterNames() method of each servlet's ServletConfig. For example:

    Enumeration e = getServletConfig().getInitParameterNames(); 

Using Servlet Initialization Parameters

Initialization parameters can be used to provide critical setup and configuration data to our servlets, in a simple and straightforward manner. The XML deployment descriptor is automatically parsed by the servlet container, so we don't need to write our own parser program, or worry about XML structures - that has already been taken care of.

Although initialization parameters can be useful, we should not use them for all our servlet configuration. The XML syntax for declaring initialization parameters in the deployment descriptor doesn't allow us to declare anything but single parameters name-value pairs. To declare a more complex data structure, we have to write our own XML documents, using a custom structure, and parse them ourselves.

For example, suppose we need to supply the following set of properties (a set of authorized servers) to our servlets:

    server1.myhost.com    server2.myhost.com    server3.myhost.com 

Using initialization parameters, there would no straightforward way to declare such a collection of similar attributes, but using our own, custom XML document we could declare them as:

    <servers>      <server>server1.myhost.com</server>      <server>server2.myhost.com</server>      <server>server3.myhost.com</server>    </servers> 

Another reason for using a custom XML file rather than initialization parameters, is that it makes it possible to modify properties at run time. The application deployment descriptor is parsed by the servlet container at initialization time, and accessible properties, such as servlet initialization parameters, are stored in memory. If we need to alter the value of an initialization parameter, we have to restart the application server for the changes to take affect. However, if we declared our own XML document to store configuration data, we would be able to monitor it for changes and reload the document as required. That way, we would be able to make changes to our application configuration without having to restart the server. In the enterprise, where computer system uptime is extremely precious, this is a powerful feature.

start sidebar

The purpose of initialization parameters is to provide fundamental initialization properties, such as the logical names of application components, or the location of more generic configuration files. For more detailed data, that may be modified at run time, we should use custom XML documents.

end sidebar

Servlet XML Configuration

We'll implement an abstract, generic, configuration class, Config, that can be extended for various purposes. To actually work with the parsed contents, we'll need to define specific extensions of this class that declare public methods for retrieving parsed values. For example, to develop a class for authenticating a user against an LDAP directory we would create an extension of our base class that reads LDAP server configuration.

We will be using the Document Object Model (DOM) to parse the XML. Using the DOM requires the entire XML document to be read into memory and stored in a tree structure. This method can be memory-intensive but it allows us to work with a structured object hierarchy and as we will generally be working with rather small configuration files they will not take up a great deal of memory.

Implementing the Config Class

Each Config instance stores a reference to the root element of the document in question. Since we will be using the DOM for parsing the XML, we can iterate through the whole document from the root element reference:

    package persistence;    import java.io.InputStream;    import javax.servlet.ServletContext;    import javax.xml.parsers.*;    import org.xml.sax.InputSource;    import org.w3c.dom.*;    public abstract class Config {      protected Element root; 

The init() method takes a reference to the application's servlet context and the path to the XML file that should be parsed as arguments. It locates the specified XML document through the getResourceAsStream() method of the ServletContext (assuming the supplied XML document path can be resolved relative to the servlet context's root directory). Once the resource stream has been resolved, the init() method parses the document into memory and stores a reference to the XML root element in the root instance variable. Nothing is done with this element in the Config class. It is up to the extensions of this class to handle the document appropriately:

      protected void init(ServletContext sctx, String xmlFile)          throws Exception {        InputStream is = null;        try {          is = sctx.getResourceAsStream(xmlFile);          DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();          DocumentBuilder builder = factory.newDocumentBuilder();          Document doc = builder.parse(new InputSource(is));          root = doc.getDocumentElement();        } finally {          if (is != null) {            is.close();          }        }      } 

To access individual elements of the XML document, we declare a general business method that can be used by subclasses of the Config class. This method, getElementText(), takes the name and parent of the element that should be obtained as arguments. It returns the value of the element in question as a string. If the specified parent element does not contain the given child element, a value of null is returned:

      protected String getElementText(Element parent, String name) {        NodeList nodeList = parent.getElementsByTagName(name);        if (nodeList.getLength() == 0) {          return null;        }        Element element = (Element) nodeList.item(0);        StringBuffer sb = new StringBuffer();        for (Node child = element.getFirstChild();             child != null;             child = child.getNextSibling()) {          if (child.getNodeType() == Node.TEXT NODE) {            sb.append(child.getNodeValue());          }        }        return sb.toString().trim();      } 

Since we store the whole XML document as an object in memory, it is a good idea to release the document object to free up resources as soon as we have finished using it:

      protected void cleanup() {        root = null;      }    } 

Now that we have implemented our abstract configuration class, we will be able to work with XML documents by extending Config and providing getter methods for all the relevant XML properties. We will look at examples using:

  • DataSourceConfig - for reading JDBC data source properties

  • LdapConfig - for reading LDAP server specification

  • AuthenticationConfig - for reading user authentication properties



 < 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