October 24, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Deployment of Web Applications in Jakarta Apache Tomcat 5

  • August 8, 2006
  • By Richard G. Baldwin
  • Send Email »
  • More Articles »

Java Programming Notes # 696


Preface

Normally when I write these tutorials, I try to keep them from becoming personal.  I attempt to approach the subject from a purely professional and impersonal viewpoint.  However, that is not the case with this tutorial.  In this tutorial, I will become personal and share some of my experiences with you.

Why did I write this tutorial?

A couple of weeks ago, I decided that I had been procrastinating long enough and it was time for me to learn what Ajax technology is all about.  I had a general idea of the technology based on some articles that I had read, and I had found several applications such as Google Maps and Google Suggest to be very impressive.  Realistically, however, I didn't have any idea how to implement an Ajax application.

Two promising Ajax technologies

So, I did a little research at Google and quickly came up with the following two competing technologies for developing Ajax web applications that I found to be very interesting:

I probably could have found some more if I had continued to search, but I decided that these two would be good for starters.

GWT got my attention

The GWT folks at Google got my attention very quickly on the basis of the following statement:

"Google Web Toolkit (GWT) is a Java development framework that lets you escape the matrix of technologies that make writing AJAX applications so difficult and error prone. With GWT, you can develop and debug AJAX applications in the Java language using the Java development tools of your choice. When you deploy your application to production, the GWT compiler translates your Java application to browser-compliant JavaScript and HTML."

ThinWire sounded good also

Similarly, the folks at ThinWire got my attention with very interesting descriptions of their technology such as the following:

  • Familiar event-driven GUI programming model
  • Develop exclusively in server-side language only
  • Never use HTML, CSS, or JavaScript again
  • Program exclusively in Java
  • All Major Browsers Supported
  • Deploy on any Java Servlet Container (including Apache Tomcat)
  • Also Runs on Nokia 770 Internet Tablet

My strong suite is Java

Since my strong suite is Java and not JavaScript, I was pleased to learn that there are at least two emerging technologies that make it possible to develop Ajax applications exclusively using Java.

Interesting applications already on line

In addition to the interesting Google applications that I mentioned earlier, I was also impressed by the ThinWire claim that much of the production business software currently being developed by Custom Credit Systems (CCS) is being developed using the ThinWire technology.

Download and get started

So, I downloaded both products and started working with them, concentrating on their documentation and their sample web applications.

Google Web Toolkit

I had no difficulty compiling the GWT Kitchen Sink sample program from Java to a combination of HTML and JavaScript files and running it in a local directory.  However, on the strength of a very cursory look, I wasn't overjoyed with the overall development procedure.  It will take some getting used to but is certainly better than having to program using JavaScript.

The ThinWire sample application

The ThinWire SDK comes with a web application called simpleapp that is ready to be deployed into a Java Servlet Container.  It is also supposed to be possible to run it locally according to the following statement that appears in one of their ReadMe files.

"To help get you up and running quickly, this SDK includes a trimmed down version of Apache Tomcat v5.5. The steps for running the Tomcat server and loading a demo are: ..."

However, I was unable to get simpleapp to run locally, so I took another approach.

Need to deploy the ThinWire sample web application

When I couldn't get the application to run in the manner described in the ThinWire literature, I decided that I would simply need to deploy the ThinWire simpleapp web application into a jakarta-tomcat-5.0.27 system that I keep on my local system for testing JSP pages and servlets.  (See the earlier lesson entitled Getting Started with Jakarta Tomcat, Servlets, and JSP.)

Oops, something is missing here

After making that decision, it didn't take me very long to realize that if I was going to be deploying complex web applications involving servlets and JSP pages, I would need to learn a great deal more about the deployment of web applications than I already knew.

(Although I had tested numerous simple JSP pages and servlets using Tomcat, I had never given any thought to how to deploy a web application in any way other than in the default ROOT directory of the Tomcat server.)

Ajax to the back burner

So, I put the Ajax project on the back burner and embarked on an effort to learn more about deploying web applications.  (I will resurrect the Ajax project later.)  I spent the next few days pouring through the documentation in order to get a handle on the deployment of web applications.

Apache Tomcat documentation

I began with the rather voluminous Apache Jakarta Tomcat 5 Servlet/JSP Container documentation with particular emphasis on the Application Developer's Guide.  Unfortunately, after several hours with this document, I erroneously concluded that in order to deploy web applications in Tomcat, I would also need to learn how to use Apache Ant.  I downloaded, installed, and tested Apache Ant.

My mama didn't raise me to be a server administrator!

After a couple of days of pouring through documentation, I was ready to throw up my hands in exasperation.  Fortunately, after a good night's sleep and a few days break while grading mid-term exams, I was able to steel myself to get back on the deployment project with vigor.

Didn't need Apache Ant after all!

After spending quite a lot of time with the rather overwhelming documentation for Apache Ant, continuing my studies of the Tomcat documentation, and making several passes through the Java(TM) Servlet API Specification 2.2, I finally concluded that all of the emphasis on Apache Ant in the Application Developer's Guide was a smokescreen that was seriously clouding the issue.  Once I came to that conclusion, things went rather smoothly.

Lots of time invested

Fortunately, as a Professor of Computer Science at a local college, I usually have plenty of time available between classes to pursue interesting technical issues that fall within my teaching specialty.  (That partially explains how I have been able to publish more than 500 online programming tutorials during the past ten years.)

You probably don't have a lot of extra time

However, on the basis of many years in private industry before becoming a college professor, I also realize that most of you who are in the working world don't have the luxury of expending this level of time and effort trying to solve knotty technical problems.  For that reason, I decided to publish my new-found knowledge in this area for the benefit of those of you who may find it useful.

Where do thing stand now?

I believe that I now understand the rather complex directory structure in the directory tree that comprises the jakarta-tomcat-5.0.27 software installation. At least, I understand those parts of the directory tree that are important in the deployment of web applications.  (Obviously, there are many items in that directory tree for which I don't have a clue as to the reason for their existence.)

Manual creation and deployment of web applications

I also now understand how to create a compatible web application project structure and how to manually deploy the project into the Tomcat directory tree.  I have successfully deployed both the ThinWire simpleapp web application and the GWT KitchenSink web application.  Finally, I have also created and deployed my first web application using the ThinWire framework.  (How to do that will be the topic of a future tutorial lesson.)

Apache Ant is another story

At this point, I have been successful in using Apache Ant to create the required directory structure for a web application that I can manually deploy into Tomcat, but I have not been successful in using Apache Ant to automatically deploy the application.  This will require me to gain a detailed understanding of three or four non-trivial XML configuration files.

May not go that far

Since I don't have a frequent need to deploy large web applications, I haven't yet decided if I will invest the time and effort necessary to learn how to automatically deploy such web applications using Apache Ant.  I may decide to be satisfied with manual deployment.

Would learn it if I needed it

However, if I did have a frequent need to deploy large web applications, there would be no question in my mind that learning how to use Apache Ant for project deployment would be well worth my time and effort.  There are a lot of details involved in doing it manually, and it is very easy to make mistakes.

Viewing tip

You may find it useful to open another copy of this lesson in a separate browser window.  That will make it easier for you to scroll back and forth among the different listings and figures while you are reading about them.

Supplementary material

I recommend that you also study the other lessons in my extensive collection of online Java tutorials.  You will find those lessons published at Gamelan.com.  However, as of the date of this writing, Gamelan doesn't maintain a consolidated index of my Java tutorial lessons, and sometimes they are difficult to locate there.  You will find a consolidated index at www.DickBaldwin.com.

General Background Information

I will begin by referring you to one of my earlier lessons entitled Getting Started with Jakarta Tomcat, Servlets, and JSP.  In that lesson you will learn how to use information provided by Marty Hall to install a preconfigured version of Tomcat 5 as a localhost servlet/JSP container on a Windows system, and how to install servlets and JSP documents on that container. 

Install in the ROOT directory tree only

That lesson will teach you only how to install servlets and JSP documents in the default ROOT directory tree, which doesn't require you to do much of anything special.

Deploy web applications outside the ROOT directory tree

The purpose of this lesson is to teach you how to deploy web applications outside of the default ROOT directory tree.

The entire jakarta-tomcat-5.0.27 directory tree

Figure 1 shows the entire directory tree that constitutes the servlet container software known as jakarta-tomcat-5.0.27, (also known as the Apache Tomcat server).


Figure 1

Most interesting parts of the directory tree

Once the server is installed and operational, the parts of the tree that are of most interest are:

  • jakarta-tomcat-5.0.27binstartup.bat (startup.sh for Linux users)
  • jakarta-tomcat-5.0.27binshutdown.bat (shutdown.sh for Linux users)
  • jakarta-tomcat-5.0.27commonlib ...
  • jakarta-tomcat-5.0.27webapps ...

Startup and shutdown

The first two items in the above list are scripts that are run to start the server when it is not running and to stop it when it is running.  The .bat files are used to start and stop the server under the Windows operating system.  I believe that the .sh files are used to start and stop the server under the Linux operating system, but I don't have any personal experience using them.

jakarta-tomcat-5.0.27commonlib ...

Although I haven't used this feature, according to the documentation, you can deposit JAR files containing classes in this directory and they will become available to JSP pages when they are being compiled as well as to both JSP pages and servlets when they are being executed.

jakarta-tomcat-5.0.27webapps ...

This is the directory sub-tree that will be of primary interest to us for the remainder of this lesson.  Hereafter, I will simply refer to the directories in this sub-tree by their names and won't qualify those names with the path to the directory.

Preview

In this lesson, I will explain how to create and manually deploy four different sample web applications (two of which are Ajax applications) in a jakarta-tomcat-5.0.27 application server.

In addition, I will share what I have learned so far regarding the following two competing Ajax web application development technologies.  Both of these technologies are based on developing the application by writing Java source code.  However, each technology takes a radically different approach to the creation of the Ajax web application.

Discussion and Sample Code

Before going any further, I need to point out that the remaining discussion in this lesson is predicated on the assumption that the Tomcat server is configured as described in my earlier lesson entitled Getting Started with Jakarta Tomcat, Servlets, and JSP.

Simple HTML or JSP Pages

Let's begin with the simplest situation, which is to install an HTML page or a JSP page on the server with no intent that it be part of a web application, and no intent that it be separable from other HTML pages or JSP pages on the basis of a path.  (Separable only by the name of the file.)

Installing an HTML file or a JSP file

The easiest thing to do in this case is to simply copy the HTML file or the JSP file into the ROOT directory that is highlighted in Figure 2.


Figure 2

An HTML file and a JSP file

As you can see, the ROOT directory in Figure 2 contains an HTML file named Hello.html, as well as a JSP file named Inew2338_052.jsp.  When the Tomcat server is running, either of these files can be accessed by any browser that has access to the server.  For example, to download and render the file named Hello.html when the server is running as localhost, just point your browser to the following URL:

http://localhost/Hello.html

Similarly, to cause the JSP file to be executed, downloaded, and rendered, just point your browser to the following URL:

http://localhost/Inew2338_052.jsp

The server is preconfigured to make this work.

Installing a servlet

Assume that you want to install a servlet (that has no package designation) on the server with no intent that it be part of a web application, and no intent that it be separable from other servlets on the basis of a path.  (Separable only on the basis of the file name.)

The easiest thing to do in this case is to copy the servlet class file into the classes directory that is highlighted in Figure 3.


Figure 3

The HelloServlet.class file

As you can see, among other things, the classes directory (which is part of the ROOT sub-tree) contains a servlet file named HelloServlet.class.  When the Tomcat server is running, this servlet is available to any browser that has access to the server.  To cause this servlet to be executed when the server is running as localhost, point your browser to the following URL:

http://localhost/servlet/HelloServlet

Note that the word servlet is required as part of the URL in the case where the servlet is part of the ROOT sub-tree.  (That won't be the case for named web applications.)

The coreservlets, org, and lib directories

These three directories (shown as children of the classes directory in Figure 3) are part of the standard preconfigured installation.  (See the earlier lesson entitled Getting Started with Jakarta Tomcat, Servlets, and JSP.)

They were populated with source files, class files, and JAR files when the server program was installed.  I'm not sure of the purpose of the first two, but they probably have something to do with the sample applications that came with the server software.  I do have an idea of the purpose of the lib directory, and you will too once you finish studying this lesson.

The Web Application Named WebApp001

Moving up a couple of steps in complexity, this is a web application that is identifiable by the name of the application:  WebApp001 (This is what I would refer to as a named web application.)

The name of the application

The name of the application is the same as the name of the directory that forms the root of a directory tree containing all the files that make up the application (exclusive of library files) as shown highlighted in Figure 4.


Figure 4

As I understand it, the root of the directory tree for a named application must be a child of the directory named webapps.

Running the application

To run this application, you call it out by name.  For example, to run the application, point your browser to the following URL (where the URL ends in the name of the directory that forms the application root):

http://localhost/WebApp001/
This will cause a file named index.html located in the directory named WebApp001 to be downloaded by default, which in turn will cause the application to be launched.

The complete file/directory tree

This web application consists of the directories and files in the directory sub-tree that is rooted in the directory named WebApp001 shown in Figure 5:

jakarta-tomcat-5.0.27
  webapps
    WebApp001 
      index.html
      WebApp001.jsp
      WEB-INF 
        web.xml
        classes
          demopackage 
            WebApp001.class
Figure 5

As mentioned before, I believe that the application root directory (WebApp001) must be a child of the directory named webapps, which is a child of the top-level directory in the Tomcat server program.

Compare Figure 5 with the tree structure shown in Figure 4 and you should find that they match.  (Directories are identified by boldface in Figure 5.)

A near-minimal tree structure

Except for the fact that there is a package named demopackage involved, (which requires one extra directory), this web application has just about the minimum number of directories possible for a web application containing one or more servlets.

As I understand it, a web application containing one or more servlets must include the following items as a minimum:

  • The application root directory (named WebApp001 for this application in Figure 5).
  • The standard directory named WEB-INF.
  • The standard Deployment Descriptor file named web.xml.
  • The standard directory named classes.

Apparently the first three items in the above list are required for all web applications even if they don't contain any servlets, but instead contains only HTML and/or JSP files.

Where to put the files

All HTML files, JSP files and other files that may be accessed directly by the client browser should be placed in the application root directory.

All servlet class files should be placed in the directory named classes or one of its subdirectories.

The standard directory named WEB-INF

Part of what the servlet specification has to say about this directory is shown in Figure 6.

A special directory exists within the application hierarchy named “WEB-INF”.  This directory contains all things related to the application that aren’t in the document root of the application.  It is important to note that the WEB-INF node is not part of the public document tree of the application.  No file contained in the WEB-INF directory may be served directly to a client.

The contents of the WEB-INF directory are:

  • /WEB-INF/web.xml  deployment descriptor
  • /WEB-INF/classes/*  directory for servlet and utility classes.  The classes in this directory are used by the application class loader to load classes from.
  • /WEB-INF/lib/*  jar area for Java ARchive files which contain servlets, beans, and other utility classes useful to the web application.  All such archive files are used by the web application class loader to load classes from.
Figure 6

As you can see in Figure 5, this application includes the first two items in the list in Figure 6, but doesn't include the directory named lib(That directory will be included in the application named WebApp002.)

The Deployment Descriptor file named web.xml

This file is required in every named web application deployed on the Tomcat server outside the default ROOT directory tree, even if it doesn't contain servlet classes or other class files.  For example, the Google KitchenSink application mentioned earlier doesn't contain any class files but it still requires the directory named WEB-INF containing the Deployment Descriptor file named web.xml.  However, it doesn't need to have a classes directory as a child of the WEB-INF directory.

When all else fails, read the specs

You can read more about the web.xml file in Section 13 of the Java(TM) Servlet API Specification 2.2.  According to the specification, "The Deployment Descriptor conveys the elements and configuration information of a web application between Developers, Assemblers, and Deployers."

The Deployment Descriptor file for WebApp001

The contents of the Deployment Descriptor file for the application named WebApp001 are shown in Listing 1.

<!DOCTYPE web-app 
  PUBLIC "-//Sun Microsystems, Inc.
  //DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

  <display-name>zzz</display-name>
  <description>
  This is a simple web application designed to illustrate
  the minimal required directory structure in the manual
  deployment of a web application consisting of a JSP 
  page and a servlet in jakarta-tomcat-5.0.27.
  </description>

  <servlet>
    <servlet-name>zzz</servlet-name>
    <servlet-class>demopackage.WebApp001</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>zzz</servlet-name>
    <url-pattern>/WebApp001</url-pattern>
  </servlet-mapping>

</web-app>


Listing 1

As you can see from Listing 1, the file named web.xml is an xml file.  Hopefully you already know something about xml files.  If not, you can learn quite a lot about xml files at my web site.

The DOCTYPE and DTD sections

If you already know about xml files, the DOCTYPE and DTD sections at the beginning of Listing 1 will probably make sense to you.  If not, don't worry about it.  As I understand it, you can simply copy this material into your own web.xml files and you should be good to go.

The element structure

The element structure in the Deployment Descriptor file is critical.  Proper nesting (and probably order as well) must be maintained.  According to the specification, many different types of optional elements can be included in the file.

Probably a minimal structure

I believe that with the possible exception of the display-name and description elements, (which may or may not be optional), Listing 1 shows the minimal structure of the web.xml file for a web application that contains servlets.

I will discuss the different elements in the web.xml file shown in Listing 1 in the following sections.  Be aware, however, that there are many more optional element types that can be included in a Deployment Descriptor file.

The display-name element

According to the specification, "The display-name element contains a short name that is intended to be displayed by GUI tools."

As you can see in Listing 1, you aren't required to make this name meaningful, but you probably should.  As mentioned above, I am unsure as to whether or not this element is required, but even if it isn't required, it would probably be a good idea to include it in your Deployment Descriptor file anyway.

The description element

According to the specification, "The description element is used to provide descriptive text about the parent element."

Once again, I'm not sure if this element is optional, but even if it is, it would probably be a good idea to include it for the later benefit of you and others.

The servlet element

In Listing 1, the servlet element serves as a nesting container for the following two elements:

  • servlet-name
  • servlet-class

According to the specification, "The servlet element contains the declarative data of a servlet. If a jsp-file is specified and the load-on-startup element is present, then the JSP should be precompiled and loaded."

I won't attempt to explain the meaning of the second sentence in the above quotation, other than to say that it doesn't apply to this simple application.

The servlet-name element

According to the specification, "The servlet-name element contains the canonical name of the servlet."

Once again, as you can see in Listing 1, this name doesn't have to be meaningful, but it probably should be.

The servlet-class element

According to the specification, "The servlet-class element contains the fully qualified class name of the servlet."

The requirement here is very specific, and this element is clearly not optional.  The content of this element must be the name of the servlet class showing the full path relative to the directory named classes.  In other words, the directory named classes is treated as the root of a sub-tree for servlet class files.

The effect of declaring packages

If your servlets are not placed in packages, the content of this element would simply be the name of the servlet class.  However, if your servlets are placed in packages, the tree structure underneath the directory named classes must reflect the package structure, and this in turn must be reflected in the content of the servlet-class element.

(As you will see in the source code for this servlet later, the servlet class was placed in the package named demopackage.  This is reflected in the sub-tree structure shown in Figure 4 and Figure 5, and in the content of the servlet-class element of the Deployment Descriptor shown in Listing 1.)

The servlet-mapping element

In Listing 1, the servlet-mapping element serves as a nesting container for the following elements:

  • servlet-name
  • url-pattern

According to the specification, "The servlet-mapping element defines a mapping between a servlet and a url pattern."  I will explain more about just what this means shortly.

The servlet-name element (again)

As with the previous instance of an element named servlet-name, the content of this element does not have to be meaningful.  However, I believe that it must match the earlier instance of the element having the same name as shown in Listing 1.

The description of this element given earlier applies here also.

The url-pattern element

According to the specification, "The url-pattern element contains the url pattern of the mapping. Must follow the rules specified in Section 10 of the Servlet API Specification."

Let me explain this with an example.  As I explained earlier, and as you can see from Figure 3, the classes directory in the ROOT sub-tree contains a servlet class file named HelloServlet.class.  To cause this servlet to be executed, you would point your browser to the following URL:

http://localhost/servlet/HelloServlet

Note that this URL ends with the name of the servlet class file.

Not necessary to use the class file name

The url-pattern element makes it possible to execute the servlet using a name other than the actual name of the servlet class file.  For example, this may be useful if the name of the servlet file is long and ugly, and you would like to give the user a servlet name that is easier to type and easier to remember.

In this application, I caused the content of the url-pattern element to be the same as the name of the servlet class file.  As a result, I can execute the servlet by pointing my browser to

http://localhost/WebApp001/WebApp001

However, had I wanted to cause this servlet to be accessible under a different name, I could have caused the content of the url-pattern element to be something different, such as joe for example.  In that case, the user would execute the servlet by pointing the browser to

http://localhost/WebApp001/joe

And that concludes the discussion of the Deployment Descriptor file named web.xml for this application.

The remaining files

My objective in this lesson is to teach you how to deploy web applications, and not how to develop them.  You will find other lessons on my web site that teach you how to write JSP pages and servlets, and you can find numerous HTML tutorials on the web.

However, I will provide listings of the remaining files in this web application so that you can create the application and deploy it on a Tomcat server on your own machine.

Before doing that, however, I will show you some screen shots so that you will know what to expect when you run the application.

The main page

To launch this web application, point your browser to the following URL:

http://localhost/WebApp001/

As explained earlier, this should cause the file named index.html located in the directory named WebApp001 to be downloaded and rendered producing the screen output shown in Figure 7.


Figure 7

Execute the JSP page

Figure 7 contains a hyperlink to a JSP page.  If you click that link, the JSP page defined by the file named WebApp001.jsp contained in the directory named WebApp001 (see Figure 5) should be executed with the results being downloaded and rendered by your browser.  This should produce the screen output shown in Figure 8.


Figure 8

Execute the servlet

If you go back to Figure 7 and click the Servlet link, this should cause the servlet program defined by the file named WebApp001.class contained in the demopackage directory (see Figure 5) to be executed.  The output produced by the servlet should be downloaded and rendered by your browser producing the screen output shown in Figure 9.


Figure 9

The index.html file

The file named index.html is shown in its entirety in Listing 2.

<html>
<head>
<title>WebApp001</title>
</head>
<body>
<h1>WebApp001</h1>
<p>Illustrates minimal deployment directory 
structure in Apache-Tomcat 5.0.27</p>

<p>Select one of the following links:
<ul>
<li><a href="WebApp001.jsp">JSP page</a>.
<li><a href="WebApp001">Servlet</a>.
</ul>
</body>
</html>

Listing 2

A straightforward HTML file

This is a straightforward HTML file containing a couple of hyperlinks.  One link points to the JSP file and the other link points to the servlet file.  However, there is one thing about this file that is worth pointing out and explaining.  Note that neither of the hyperlink references highlighted in boldface in Listing 2 contain path information.  One might wonder how the system can find the referenced files.

There is nothing remarkable about the link to the file named WebApp001.jsp.  This file is in the same directory as the file named index.html, so no path information is needed.

Resolution of the servlet reference

However, the resolution of the servlet reference in the second boldface hyperlink in Listing 2 is somewhat more significant.  The information required for the system to locate and read the file named WebApp001.class is provided in the servlet-class and url-pattern elements of the Deployment Descriptor file named web.xml(See Listing 1 and the discussion of the servlet-class and url-pattern elements following Listing 1.)

The second boldface reference in Listing 2 uses the value of the url-pattern element defined in the Deployment Descriptor shown in Listing 1.  The system uses this information, along with the path information given by the servlet-class element in Listing 1 to locate, read, and execute the file named WebApp001.class.

The WebApp001.jsp file

The JSP file named WebApp001.jsp is shown in Listing 3.

<!--File WebApp001.jsp -->

<html>
  <title>WebApp001</title>
     <body>
     <h1>WebApp001 JSP Page</h1>
     <h2>Hello, JSP world!</h2>
     <p>The JSP page for a Web App designed
     to illustrate the minimal required
     directory structure.</p>

     <% for (int i=0; i<6; i++) { %>
         <br> 
         <%= i %>
     <% }//end for loop %>

     <h3>Isn't this fun</h3>

     </body>
</html>

Listing 3

If you are familiar with JSP programming, you should have no difficulty understanding the code in this file and matching it up with the display shown in Figure 8.  Otherwise, you may want to study the lessons on JavaServer Pages on my web site.

The WebApp001.java file

The source code that was compiled to produce the file named WebApp001.class in the demopackage directory in Figure 5 is shown in its entirety in Listing 4.

/*File WebApp001.java,
Copyright 2006, R.G.Baldwin

The purpose of this program is to illustrate a very simple 
servlet that can be deployed in a minimal directory 
structure in jakarta-tomcat-5.0.27.

The servlet was tested using jakarta-tomcat-5.0.27 as
localhost running under WinXP.

The servlet produces the following text in the
browser window in large green letters.

Hello Big Green World
**********************************************************/
package demopackage;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class WebApp001 extends HttpServlet{
  public void doGet(HttpServletRequest req,
                    HttpServletResponse res)
                    throws ServletException,IOException{

    res.setContentType("text/html");
    PrintWriter out = res.getWriter();

    out.println("<html>");
    out.println("<head><title>WebApp001</title></head>");
    out.println("<body>");

    out.println(
          "<h1 align="center"><font color="#00FF00">");
    out.println("Hello Big Green World");
    out.println("</font></h1>");

    out.println("</body></html>");
  }//end doGet()
}//end class WebApp001

Listing 4

If you already understand servlet programming, you should have no difficulty understanding the code in Listing 4 and matching it up with the screen output shown in Figure 9.  Otherwise, you may want to study the servlet lessons on my web site.

The package named demopackage

The most notable thing about Listing 4 is the package declaration.  The class file produced by compiling the code in Listing 4 resides in the package named demopackage.  This requires that the class file be placed in a directory named demopackage, which is a child of the directory named classes in Figure 4 and Figure 5.

That concludes the discussion of the web application named WebApp001.

The Web Application Named WebApp002

This web application is an enhanced version of the web application explained above named WebApp001.

Perhaps the best way to introduce you to the enhancements will be to show you some screen shots that illustrate most of the enhancements.

Launching the web application

The web page in the file named index.html, which is downloaded and rendered in order to launch the application, is shown in Figure 10.


Figure 10

Two major differences

If you compare Figure 10 with Figure 7, you should see two major differences between the two.  The first difference is the inclusion of the image in the upper-left corner of Figure 10.  As you will see later, a special non-required directory named images was constructed (as a child of the application root directory) to provide a location to house the file for this image.

The second difference is the inclusion of an extra hyperlink labeled Documentation at the bottom of Figure 10.  Another special non-required directory named docs was constructed (as a child of the application root directory) to house the documentation files.

(The image file and the documentation file could be housed somewhere else within the directory structure, but this helps to keep the overall organization cleaner.)

Of course, as you will see later, inclusion of the image and the new hyperlink required corresponding changes to the file named index.html.

The JSP page output

The screen shot in Figure 11 shows the screen output produced by selecting the JSP page hyperlink in Figure 10.


Figure 11

If you compare Figure 11 with Figure 8, you will see that the only change was a small modification in the output text produced by the JSP file.

The servlet output

The screen shot in Figure 12 shows the screen output produced by selecting the Servlet hyperlink in Figure 10.


Figure 12

If you compare Figure 12 with Figure 9, you will see that this enhanced version of the web application displays the date and time each time the servlet is executed.  This may not seem like much, but it represents a very important change.

Why is this so important?

The servlet code in this application instantiates an object of a class named WebApp002Helper and invokes a method named getDate on that object in order to get and display the date and time.  Again, this may not sound like much.  The important thing is that the class file for the WebApp002Helper class in encapsulated in a JAR file, and that JAR file is stored in a new directory named lib, which is a child of the directory named WEB-INF.

The Documentation output

The screen shot in Figure 13 shows the screen output produced by selecting the Documentation hyperlink in Figure 10.


Figure 13

This is a new output for which there was no corresponding output in the application named WebApp001Figure 13 shows the rendering of a file named WebApp002.html, which was stored in the new docs directory. 

A good place to put javadocs and user manuals

While the output shown in Figure 13 is rather trivial, this would be a very good place to store complete documentation on the web application, such as documentation produced by the javadoc utility program for example.

The directory named src

There is one final difference between this enhanced application and the earlier application named WebApp001 that is not shown in the screen shots.  This difference is the inclusion of a new directory named src as a child of the application root directory.  This directory is used as a location to house the source code for the application.

The directory structure

The directory structure for this web application is shown in Figure 14.


Figure 14

The new directories and files

If you compare the directory structure of WebApp002 in Figure 14 with the directory structure of WebApp001 in Figure 4, you will see the following new directories in Listing 14.  These directories contain the files identified with the directory names in the following list:

  • WebApp002docs - contains WebApp002.html documentation file.
  • WebApp002images - contains ColorWheel.gif image file.
  • WebApp002src - doesn't contain any files.
  • WebApp002srcdemopackage - contains Java source code files for WebApp002 and WebApp002Helper classes.
  • WebApp002WEB-INFlib - contains WebApp002.jar file, which encapsulates the file named WebApp002Helper.class.

The required directories and files

The directories in Figure 14 that match the required directories in Figure 4, along with the files that they contain are shown in the following list:

  • WebApp002 - contains index.html and WebApp002.jsp.
  • WebApp002WEB-INF - contains web.xml.
  • WebApp002WEB-INFclasses - doesn't contain any files.
  • WebApp002WEB-INFclassesdemopackage - contains WebApp002.class.

I will briefly discuss the new and interesting aspects of these files in the sections that follow.

The file named index.html

The file named index.html, which is stored in the WebApp002 directory, is shown in Listing 5(Compare this listing with the listing of the comparable file from the previous application shown in Listing 2.)

<html>
<head>
<title>WebApp002</title>
</head>
<body>

<table border="0">
<tr>
<td>
<img src="images/ColorWheel.gif">
</td>
<td>
<h1>WebApp002</h1>
<p>Illustrates typical deployment directory 
structure in jakarta-tomcat-5.0.27</p>
</td>
</tr>
</table>

<p>Select one of the following links:
<ul>
<li><a href="WebApp002.jsp">JSP page</a>.
<li><a href="WebApp002">Servlet</a>.
<li><a href="docs/WebApp002.html">Documentation</a>.</ul>
</body>
</html>

Listing 5

Although Listing 5 contains some new material having to do with cosmetics, the only new material of any technical significance in Listing 5 is shown highlighted in boldface.

Reference to the image file

The first boldface line in Listing 5 is a reference to the image file stored in the directory named images.  Note that a path is provided in this case, and that path is relative to the application root directory named WebApp002.

Obviously this reference causes the image to be displayed in the upper-left corner of Figure 10.

Reference to the documentation file

The second boldface line in Listing 5 is a reference to the documentation file stored in the directory named docs.  Once again, a path is provided and it is relative to the application root directory.

This reference produces the Documentation hyperlink at the bottom of Figure 10.

The file named WebApp002.jsp

The file named WebApp002.jsp, which is also stored in the WebApp002 directory, is shown in Listing 6(Compare this listing with the listing of the comparable file from the previous application shown in Listing 3.)

<!--File WebApp002.jsp -->

<html>
  <title>WebApp002</title>
     <body>
     <h1>WebApp002 JSP Page</h1>
     <h2>Hello, JSP world!</h2>
     <p>The JSP page for a Web App designed
     to illustrate a typical directory 
     structure.</p>

     <% for (int i=0; i<6; i++) { %>
         <br> 
         <%= i %>
     <% }//end for loop %>

     <h3>Isn't this fun</h3>

     </body>
</html>

Listing 6

If you compare Listing 6 with Listing 3, you will see that with the exception of some minor wording changes in the displayed text, there is no difference between the two files.  Hence, the JSP pages for both applications are essentially the same.

The file named WebApp002.java

The source code servlet file for this application is shown in Listing 7.  This source code file is stored in the directory named WebApp002srcdemopage.  The compiled version of this file is stored in the directory named WebApp002WEB-INFclassesdemopackage.

/*File WebApp002.java,
Copyright 2006, R.G.Baldwin

The purpose of this class is to illustrate a very simple 
servlet that can be deployed in a typical directory 
structure in jakarta-tomcat-5.0.27.

This servlet invokes a method named getDate on an object 
instantiated from a helper class (in the same package 
named) WebApp002Helper.  The purpose of invoking the
method is to illustrate the use of classes stored in a JAR 
file located in the WEB-INF/lib directory.

The servlet was tested using jakarta-tomcat-5.0.27 running
as localhost under WinXP.

The servlet produces the following text in the
browser window in large green letters.

Hello Big Green World

The green text is followed by text similar to the following
that is returned by the method named getDate belonging to
an object of the WebApp002Helper class:

Tue Jul 25 09:44:49 CDT 2006
**********************************************************/
package demopackage;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class WebApp002 extends HttpServlet{
  public void doGet(HttpServletRequest req,
                    HttpServletResponse res)
                    throws ServletException,IOException{

    res.setContentType("text/html");
    PrintWriter out = res.getWriter();

    out.println("<html>");
    out.println("<head><title>WebApp002</title></head>");
    out.println("<body>");

    out.println(
          "<h1 align="center"><font color="#00FF00">");
    out.println("Hello Big Green World");
    out.println("</font></h1>");
    
    out.println("<p>" + new WebApp002Helper().getDate() 
                                                 + "</p>");

    out.println("</body></html>");
  }//end doGet()
}//end class WebApp002

Listing 7

A helper class

If you compare Listing 7 with Listing 4, you will see that the only significant difference between the two is the statement in Listing 7 that is highlighted in boldface.

The boldface statement in Listing 7 instantiates a new object of the class named WebApp002Helper and then invokes the method named getDate on that object.  For illustration purposes, this mechanism is used to get and display the current date and time as shown in Figure 12.

Why is this significant?

The significant thing here is that the class file for the WebApp002Helper class is encapsulated in a JAR file, which is placed in the WebApp002WEB-INFlib directory.  That makes the helper class file available to the servlet class.

(Both classes belong to the demopackage package, so no import directive is required to make the helper class available to the servlet class.)

The file named WebApp002Helper.java

The source code for the helper class is shown in Listing 8.  This source code file is stored in the directory named WebApp002srcdemopage.  As mentioned above, the compiled version of this file is encapsulated in a JAR file named WebApp002.jar, which is stored in the directory named WebApp002WEB-INFlib.

/*File WebApp002Helper.java,
Copyright 2006, R.G.Baldwin

The purpose of this class is to illustrate the use of
a class that is placed in a JAR file in the WEB-INF.lib 
directory in the jakarta-tomcat-5.0.27 directory structure.
The class file for this helper class can be placed in the
following location and it will work properly in conjunction
with the servlet class named WebApp002:

CATALINA_HOMEwebappsWebApp002WEB-INFclassesdemopackage

The class file can also be placed in a JAR file and the
JAR file can be placed in the following location and it 
will work properly in conjunction with the servlet class 
named WebApp002:

CATALINA_HOMEwebappsWebApp002WEB-INFlibdemopackage

Note that the JAR file must reflect the fact that the class
file is in the directory named demopackage.

Also note that the first location listed above is the same
location as the class file for the servlet class named
WebApp002, which uses this class as a helper.

The term CATALINA_HOME refers to the directory into which 
jakarta-tomcat-5.0.27 was installed, and is the base 
directory against which most relative paths are resolved.
On my machine, CATALINA_HOME resolves to 
C:jakarta-tomcat-5.0.27, which is the value of the
environment variable named CATALINA_HOME.

To create the JAR file, open a command-line window in the
directory from which this class was compiled.  Then enter
the following command:

jar cf WebApp002.jar demopackage/WebApp002Helper.class

Enter jar at the command line to see usage information and 
a list of options for the Java utility program named jar.

Tested using jakarta-tomcat-5.0.27 running as localhost 
under WinXP.
**********************************************************/
package demopackage;

import java.util.Date;

class WebApp002Helper{
  String getDate(){
    return new Date().toString();
  }//end getDate
}//end class definition

Listing 8

Other than to point out that the helper class and the servlet class are both placed in the demopackage package, the code in Listing 8 is straightforward and shouldn't require further explanation.

The file named web.xml

The Deployment Descriptor file named web.xml, which is stored in the directory named WebApp002WEB-INF, is shown in Listing 9.

<!DOCTYPE web-app 
  PUBLIC "-//Sun Microsystems, Inc.
  //DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

  <display-name>zzz</display-name>
  <description>
  This is a simple web application designed to illustrate
  the minimal required directory structure in the manual
  deployment of a web application consisting of a JSP 
  page and a servlet in jakarta-tomcat-5.0.27.
  </description>

  <servlet>
    <servlet-name>zzz</servlet-name>
    <servlet-class>demopackage.WebApp002</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>zzz</servlet-name>
    <url-pattern>/WebApp002</url-pattern>
  </servlet-mapping>

</web-app>


Listing 9

If you compare Listing 9 with Listing 1, you will see that except for a couple of minor changes highlighted in boldface, the Deployment Descriptor file for this enhanced web application is essentially the same as the Deployment Descriptor file for the earlier web application named WebApp001.

No new deployment information was required

This indicates that none of the enhancements had any bearing on the required deployment information.

Access to the files in the new src directory is not required at runtime.

Runtime access to the files in the new docs and images directories was handled by path specifications in the relevant code.

Runtime access to class files encapsulated in JAR files that are stored in the WebApp002WEB-INFlib directory is a standard part of the system and does not require special deployment instructions.

The file named WebApp002.html

The sample documentation file named WebApp002.html, which is stored in the docs directory is shown in Listing 10.

<p>This is a dummy documentation file for 
the servlet named WebApp002.</p>


Listing 10

There is nothing special about this file other than the fact that it is not a complete HTML file.  Regardless of that fact, my Firefox browser was more than happy to load it and to render it on the screen in plain text as shown in Figure 13.

The Competing Ajax Technologies

I began this lesson by telling you a little about two competing technologies for developing Ajax web applications that I found to be very interesting:

I explained that my reason for doing the research (and publishing this lesson) was based on my realization that I didn't know how to deploy the Ajax web applications produced by those two technologies.  After doing the research and learning more about the deployment of web applications, I was able to use both technologies to develop sample Ajax web applications and to deploy them onto a Tomcat server.

Radically different approaches

Although both technologies start out with Java source code, the approaches that they take to produce Ajax web applications are radically different.  The GWT approach appears to generate a lot of HTML files, XML files, JavaScript files, Cascading Style Sheet (CSS) files, and image files, but it doesn't generate any Java servlet files or other Java class files.

(Interestingly, it also doesn't generate the requisite directory named WEB-INF containing the requisite Deployment Descriptor file named web.xml.  I had to create that directory and that file manually.)

The ThinWire approach, on the other hand appears to generate only Java class files, JAR files, and the requisite Deployment Descriptor file named web.xml.

The Google KitchenSink Web Application

Although I'm not going to get into a lot of details, I will show you a little about an Ajax web application produced by the GWT.  The GWT comes with the Java source code for a web application named KitchenSink.  This sample application demonstrates many of the widgets in the Google Web Toolkit.  It is not difficult to use the toolkit to compile that source code into an Ajax web application.

Figure 15 shows the screen output produced by executing the web application on localhost and selecting the link to Menus.


Figure 15

The HTML Page Source view

If you open the Page Source view for the HTML page that produced Figure 15, it begins with a head element that consists mainly of a link element that refers to a CSS file.

The head element is followed by a body element that consists of:

  • A single script element that references a JavaScript file, and
  • An iframe element.

I am not familiar with the purpose of an iframe element.

No file named index.html

The GWT doesn't generate a file named index.html for this application.  Rather, it generates a file named KitchenSink.html, and deposits that file in the application root directory.  Therefore, the application is executed by pointing the browser to the following URL:

http://localhost/GoogleKitchenSink/KitchenSink.html

The directory structure

The directory structure for this application is shown in Figure 16.


Figure 16

The GWT created the application root directory under the name com.google.gwt.sample.kitchensink.KitchenSink.  I renamed it GoogleKitchenSink before deploying it for brevity.

The images and rembrandt directories

The GWT also generated the directories named images and rembrandt.  The images directory contains a couple of GIF files that appear to be used in an operational sense to control the screen output during the execution of the application.  The rembrandt directory contains image files, HTML files, and CSS files that appear to be used for screen output as the different links shown in Figure 15 are selected.

No WEB-INF directory

As mentioned earlier, the GWT did not generate the requisite WEB-INF directory containing the requisite Deployment Descriptor file named web.xml.  I had to create the directory and the file manually in order to deploy the application as a named web application in the Tomcat server.  Consequently, the output produced by the GWT wasn't fully ready to be deployed as a named web application.

Probably addresses a broader server market

The fact that the GWT Ajax technology doesn't generate servlets (or any Java class files for that matter) and doesn't generate a WEB-INF directory suggests to me that although Google is making it possible to develop Ajax applications using Java, they are targeting a much broader server market than just the subset of servers that meet the Sun servlet specification.  As a result, it was necessary for me to create the WEB-INF directory and populate it with the web.xml file required to meet Sun's servlet specification in order to deploy it as a named web application on the Tomcat server.

(A web application doesn't have to include servlets to operate as a named web application on the Tomcat server, but it is required to have the directory named WEB-INF containing a file named web.xml.  Presumably a named web application could consist solely of HTML files and JSP files.  After all, a JSP page is just a fancy way to have the system write and compile your servlets for you.)

Deployment without a WEB-INF directory

It should be possible to deploy this application on just about any web server regardless of whether or not it supports Java servlets.  In fact, I was able to

  • Change the name of the application root directory to GwtTest,
  • Copy the directory tree produced by GWT (without a WEB-INF directory) into the webappsROOT directory of the jakarta-tomcat-5.0.27 server, and
  • Execute it successfully from my browser. 

To execute the application in this mode, I simply pointed the browser to the following URL:

http://localhost/GwtTest/KitchenSink.html

This is what I would expect to be the case for other servers that don't support servlets.

Contents of the application root directory

Just to give you a better sense of what is going on in the GWT generation of the Ajax web application, Figure 17 shows a list of the files that are generated by the GWT and deposited in the application root directory.

05658AED8DE39976B165E750CB4D90A4.cache.html
05658AED8DE39976B165E750CB4D90A4.cache.xml
com.google.gwt.sample.kitchensink.KitchenSink.nocache.html
E89EB924DF319B972D44990AE2BB26E8.cache.html
E89EB924DF319B972D44990AE2BB26E8.cache.xml
EBD64DAD328F9113D096C80FE81835F2.cache.html
EBD64DAD328F9113D096C80FE81835F2.cache.xml
F2335895916284CA7C781586B8EF5A71.cache.html
F2335895916284CA7C781586B8EF5A71.cache.xml
FAC42F7AFC8C8BC2BF05AE784034B3EC.cache.html
FAC42F7AFC8C8BC2BF05AE784034B3EC.cache.xml
gwt.js
history.html
images
KitchenSink.css
KitchenSink.html
rembrandt
tree_closed.gif
tree_open.gif
tree_white.gif
Figure 17

Note that the two boldface items in Figure 17 are directories, which are populated as described earlier.

No Java class files

As mentioned earlier, the GWT doesn't generate any Java servlet or other class files.  As a result, once you figure out what is going on, deployment of the web application is reasonably simple.  All that is necessary is to copy the directory sub-tree that is rooted in the application root directory into the Tomcat webapps directory, and then add the requisite WEB-INF directory containing the requisite Deployment Descriptor file named web.xml.

The Deployment Descriptor file

The required web.xml file for the KitchenSink sample application was easy to generate.  The contents of that file are shown in Listing 11.

<!DOCTYPE web-app 
  PUBLIC "-//Sun Microsystems, Inc.
  //DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

  <display-name>zzz</display-name>
  <description>zzz</description>

</web-app>

Listing 11

As I mentioned earlier, I don't know if the display-name and description elements are required or not, but it is probably a good idea to include them (and to give them meaningful content, which I didn't do).

And that concludes the discussion of the deployment of the Google KitchenSink sample Ajax web application.

The ThinWire simpleapp Web Application

The ThinWire framework is delivered with a couple of sample Ajax web applications that have already been converted from Java source code to a deployable web application.  (The Java source code is also provided.)  One of those sample applications is named simpleapp and the other is named thinwire_mail.

The simpleapp web application is deployable as received because the entire directory structure for the web application has already been generated and populated.

The screen output

This web application is launched by pointing the browser to the following URL:

http://localhost/simpleapp/

The screen output shown in Figure 18 appears when the application is launched.


Figure 18

The HTML Page Source view

If you open the Page Source view for the HTML page that generated the screen output shown in Figure 18, it begins with a head element consisting mainly of a link to a CSS file.  The head element is followed by a body element consisting exclusively of script elements.  All of the script elements refer to "text/javascript" files.

Behavior of the application

When I enter my name and click the Ok button in Figure 18, the screen output changes to that shown in Figure 19.


Figure 19

When the Ok button is clicked in Figure 19, the program terminates.

Clicking the X-button

Clicking the X-button in the top right of the frame in either Figure 18 or Figure 19 causes the application to terminate immediately and causes a blank browser screen to appear.

The directory structure

The complete directory structure for this web application is shown in Figure 20.


Figure 20

The Java source and class files

Figure 20 also shows the class files (in the right panel) that are contained in the demo directory.  Presumably the file named SimpleApp.class is a servlet that was automatically generated when the original Java source code was processed to produce the web application.

The demo directory also contains the original Java source code file.

The original Java source code file

I'm not going to show you the contents of the original Java source code file because there may be republication restrictions on that code.  (You can download and examine it yourself if you want to see it.)  I will tell you, however, that it doesn't look anything like the source code for a servlet.  Rather, it looks like a simple stand-alone Java application with a main method. 

The source code file declares that it is in the thinwire.apps.demo package.  It also declares the following import directives:

  • import thinwire.ui.*;
  • import thinwire.ui.event.*;

Three JAR files

Obviously the classes being imported are not part of the standard Java library that comes from Sun.  Presumably the classes being imported are contained in the following three JAR files, which are in the lib directory:

  • commons-fileupload.jar
  • retroweaver-rt.jar
  • thinwire.jar

The Deployment Descriptor file

The only other file in the web application is the requisite Deployment Descriptor file named web.xml that is in the WEB-INF directory.  Fortunately, that file was provided because I wouldn't have known how to generate it manually.

(Once again, I'm not going to show it to you because of my uncertainty regarding republication restrictions.)

However, I will tell you that it contains essentially the same elements as Listing 1 plus an additional element named init-param.  This element in turn contains the following new elements:

  • param-name
  • param-value

Knowledge of ThinWire technology is required

Clearly to create and populate the Deployment Descriptor file requires more knowledge of the inner workings of the ThinWire technology than I have at this time.  I will learn more about this later as I continue to do research on the ThinWire Ajax web application development technology.

And that concludes my discussion of the ThinWire Ajax web application named simpleapp.

Run the Program

I encourage you to install the Tomcat server on your system (see the earlier lesson entitled Getting Started with Jakarta Tomcat, Servlets, and JSP) and to use the information that I have provided to replicate my projects named WebApp001 and WebApp002.

If you are interested in Ajax, you may also want to download the following two development frameworks and experiment with them as well:

Summary

In this lesson, I showed you how to create and manually deploy four different sample web applications (two of which are Ajax applications) in a jakarta-tomcat-5.0.27 application server.

I also shared what I have learned so far regarding two competing Ajax web application development technologies.  Both technologies are based Ajax web application development using Java source code.  However, each of the technologies takes a radically different approach to the creation of the Ajax web application.

What's Next?

I plan to continue my research into Ajax technology, particularly as it involves Java.  As I learn more about this technology, I will share what I have learned with you in the form of future tutorial lessons.


Copyright 2006, Richard G. Baldwin.  Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.

About the author

Richard Baldwin is a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is a combination of Java, C#, and XML. In addition to the many platform and/or language independent benefits of Java and C# applications, he believes that a combination of Java, C#, and XML will become the primary driving force in the delivery of structured information on the Web.

Richard has participated in numerous consulting projects and he frequently provides onsite training at the high-tech companies located in and around Austin, Texas.  He is the author of Baldwin's Programming Tutorials, which have gained a worldwide following among experienced and aspiring programmers. He has also published articles in JavaPro magazine.

In addition to his programming expertise, Richard has many years of practical experience in Digital Signal Processing (DSP).  His first job after he earned his Bachelor's degree was doing DSP in the Seismic Research Department of Texas Instruments.  (TI is still a world leader in DSP.)  In the following years, he applied his programming and DSP expertise to other interesting areas including sonar and underwater acoustics.

Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.

Baldwin@DickBaldwin.com






Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel