2007-06-13

REALM Part I: Tomcat & Servlets

This is the first in a five part series on the REALM stack. The previous introduction can be found here. In this posting I will introduce Tomcat & Servlets as well as review the basic tomcat installation, organization of a deployment, organization of your source and the actual development process. A link to source code will be provided at the end of the tutorial, and assuming you have tomcat installed you should be able to modify the included build.properties file and type "ant install". I will not cover ant or tomcat installation, as there are a number of good tutorials on the web. These applications are available for most Linux distributions. Some of this information has been taken from, "Developing Applications with Tomcat" which is available here. The Project CalculatorInc.com wants to provide a website where they allow people to do basic arithmetic operations on the web using arbitrarily large numbers. They are sure it will be the next big thing in this "web 2.0" space, however they haven't yet discovered web services or rails so they have implemented the entire thing using JSP & Servlets. Here is a link to the project source. In it is a reasonable starting place for any Servlet/JSP project, it contains the following: ant build file, JavaCC grammar, unit tests, a servlet and a jsp page. Pretty basic but we're going to use it as a starting point from which we will enhance it with Spring, add remoting to provide a web service and finally hook it up to rails. Since I recently made fun of a calculator web service, we'll create a calculator web service. It only has the basic operations (+,-,/,*,%,^) but it uses a JavaCC grammar so if you haven't used JavaCC before it's a good simple intro. The requirements are in the docs/README.txt file, but in short: Java >= 1.5, Tomcat 6 (5 probably works, 4 perhaps as well), JavaCC and Ant. That should be about it. Basic install instructions (edit build.properties, ant install test) are in that same document. What is Tomcat? First and foremost, Tomcat is a web container. A web container, according to sun is defined as follows.
"A container that implements the Web component contract of the J2EE architecture. This contract specifies a runtime environment for Web components that includes security, concurrency, life-cycle management, transaction, deployment, and other services. A Web container provides the same services as aJSP container as well as a federated view of the J2EE platform APIs. A Web container is provided by a Web or J2EE server."
That's a wordy definition. I would say, "Tomcat allows Java code to run in a web environment". It also does all of the things described above, but for the purposes of this discussion the shorter definition is fine. Secondly, Tomcat implements theJSP and Servlet API specifications. For Tomcat 6.0, which is the most recent release of Tomcat, that means the Servlet 2.5 and JavaServer Pages 2.1 specifications. These can be found here and here, respectively. In general you configure Tomcat via xml files that can be found in the conf directory. Tomcat also has its own web server. This is fine for development purposes however you almost always want to use something like mod_jk in production settings, assuming you are using Tomcat in the web tier as well as the middleware tier. There is excellent documentation for Tomcat available here. Competitors include Jetty, Geronimo, Resin, BEA WebLogic and JBoss. What is a Servlet? A servlet is a Java server application that answers and fulfills requests from clients. It's that simple. Tomcat interacts with and manages your servlets, that is one of its jobs. In terms of implementation, a servlet is a component that extends or implements classes or interfaces from the javax.servlet package or the javax.servlet.http packages. A servlet allows you to create dynamic content, and is most commonly interacted with via the HTTP protocol. Some typical uses of a servlet include:
  • Processing data submitted by an HTML form (and optionally storing it)
  • Providing dynamic content (e.g. information stored in a DB)
  • Managing state information (e.g. sessions)
Servlets have the following advantages over a typical CGI; doesn't run in its own process, stays in memory between requests, there is a single instance that handles all requests concurrently.Servlets are also typically packed in a WAR file, that is, a Web ARchive. This is the web analogy to a JAR file. Your Tomcat Installation Once you have tomcat installed (I'll assume it's in /usr/local/java/tomcat), it at a minimum should have the following directories.
  • bin - contains startup, shutdown and other scripts
  • conf - server configuration
  • lib - The jar files used by Tomcat
  • logs - Application and server log files
  • webapps - Location of servlets/web applications
  • work - Automatically generated by Tomcat, these files are often intermediary (such as compiled JSP)
Optionally, you can create the following directories.
  • classes - Classes you want available to a servlet. You may have to configure this.
  • doc - Documentation for tomcat, copy from webapps/docs
  • src - Servlet API source files.
When you deploy a webapp as source or as a WAR file, it will end up under the webapps directory. When you go to your servlet on the web, files and directories will be created under the work directory. The above should be enough hierarchy information for you to figure out where things are or should be. Your Deployment Servlets conforming to the 2.2 or later Servlet specification are required to accept a WAR file in a specified format. A WAR file has a specific directory and file hierarchy that must be conformed to and as such it often makes sense for your development environment to reflect this layout but more on that in the next section. The WAR file when unpacked is useful for development, and packed is useful for deployment. The top-level directory of your web app hierarcy is also the document root of your app. You should put your HTML/JSP/UI files there. When you deploy your application to a server, your application is assigned a context path. If your context path is /catalog, then a request URI to /catalog/index.html will fetch the index.html file from your document root. From the document root, the directory and file hierarchy will look something like this:
  • *.html, *.jsp, images, etc - Files that must be visable to the client. You can break this up in a hierarchy if your application is large.
  • WEB-INF/web.xml - The Web Application Deployment Descriptor. This XML file describes servlets, initialization parameters, container security, etc.
  • WEB-INF/classes/ - Java class files that are required for your application that are not in JAR files. Added to your classpath.
  • WEB-INF/lib/ - Contains the JAR files required for your application. Added to your classpath.
The WEB-INF/web.xml contains the Web Application Deployment Descriptor for your app. This is an XML document that defines everything about your app that the server needs to know (except the context path). The complete syntax and semantics for the descriptor are defined in Chapter 13 of the Servlet API specification, version 2.4. Also see doc/appdev/web.xml. The 2.5 API specification seems to not be available yet in PDF form. A web application must be installed in a server container, even during the development phase. A web application can be installed in several ways, however when you run "ant deploy" for this application ant will submit the built WAR file to the Tomcat installation and Tomcat will automatically unpack it for you. Your Source Code This section primarily focuses on the directory structure and build targets of your build.xml ant file. You want to separate your source code (tests and application) from your deployable application as much as possible. This makes both deployment and revision control easier. Below is the recommended hierarchy for the top level project source directory.
  • build.xml - Your ant build file
  • build.properties - Ant build properties
  • build/ - temporary home for javadocs and built war files
  • dist/ - temporary home for build classes
  • docs/ - Documents generated by javadoc or install notes, etc
  • lib/ - Jar files needed for builds and distributions
  • src/
    • src/tests/ - Your unit tests, load tests, etc
    • src/main/ - The primary java code for your servlets and application
  • web/ - User facing components (images, html, etc)
    • web/WEB-INF/ - The application
      • web/WEB-INF/web.xml - Your web application descriptor
      • web/WEB-INF/classes/ - The compiled classes from src/main/. Built for you.
      • web/WEB-INF/lib/ - JAR files from lib/. Built for you.
    • web/images/ - Images for web facing components
    • web/jsp/ - JavaServer Pages
Again, this is simply the recommended hierarchy, and the one that will be used for all the sample code. The top level build.xml file will include a properties file called build.properties. The properties file will contain build related properties such as the tomcat manager username and password and the base of your tomcat installation. The included build file has the following targets available:
  • all - Run clean target followed by compile target, to force a complete recompile.
  • clean - Delete any previous build and dist directory so that you can be ensured the application can be built from scratch.
  • compile - Transforms source files (from src/main/ directory) into object files, generally unpacked in build/WEB-INF/classes.
  • dist - Creates binary distribution of your application in a directory structure ready to be archived. Runs compile and javadoc.
  • install - Tells tomcat5 to dynamically install the web app and make it available for execution (deploy). Does not cause app to be remembered across restarts. If you just want Tomcat to recognize that you have updated classes (or web.xml) use the reload target instead.
  • javadoc - Creates Javadoc API documentation for the Java classes included in the application. Normally only done for dist.
  • list - List currently running web applications. Useful to check if app has been installed.
  • prepare - Create the build dest directory, copy static content to it. Normally executed indirectly.
  • reload - Signals tomcat to shutdown and reload. Useful when web application context isn't reloadable and you have updated classes or properties or added new jars. In order to reload web.xml you must stop and then start the web application.
  • remove - Remove the web app from service (undeploy).
  • start - Start this web application.
  • stop - Stop this web application.
  • test - Run all unit tests.
  • usage - Display a short form of the above, the default target.
In general, you will run "ant install" to build and install your application. The Development Process The Servlet/JSP development cycle mantra is "edit, test, deploy". Say it with me now, "edit, test, deploy". After you have created your base directory structure and installed your application at least once (i.e. Tomcat recognizes it) you will employ this mantra frequently. How Does it Work? Based on web/WEB-INF/web.xml (which sets our "routes" which are known as servlet mappings), by default the controller servlet will be loaded which is in the net.mobocracy.web.ControllerServlet class. When that servlet receives control, it will if the request is an HTTP GET, forward to the jsp file located at /jsp/index.jsp (a forward is essentially handing off control). If the request is an HTTP POST, it will do basic validation, instantiate the Arithmetic parser, and evaluate the arithmetic expression. On success, it sets ArithmeticSuccess for the JSP page and on failure it sets ArithmeticError. The doPost method also forwards to the /jsp/index.jsp page, but only after setting one of the previous attributes. Once the JSP page is handed control, it sees what attributes (if any) have been set by the Servlet and acts appropriately. The JSP page only has a few lines of code so it probably isn't worth discussing too much. The examples are meant to be evaluated in the source code, both in comments and interaction. The code comes in at only 338 lines, not including the build file and README so I will not spend a lot of time explaining the source here but if you have questions please leave it as a comment or send me an email. You should find the source fairly well documented. Conclusion We will be using this to build upon to take this from a JSP/Servlet architecture to a REALM project where we can utilize the wide variety of toolkits available to J2EE and the flexible front-end development environment of Ruby on Rails. After reading this you should have an understanding of one model of Servlet/JSP development using Tomcat. Below is a list of resources. Resources Tomcat http://tomcat.apache.org/tomcat-6.0-doc/index.html http://en.wikipedia.org/wiki/Apache_Tomcat http://www.coreservlets.com/Apache-Tomcat-Tutorial/ Java 1.5 http://java.sun.com/j2se/1.5.0/docs/api/index.html JavaCC https://javacc.dev.java.net/doc/docindex.html http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-cooltools.html http://www.idevelopment.info/data/Programming/java/JavaCC/The_JavaCC_FAQ.htm Ant http://ant.apache.org/manual/index.html Servlets http://www.servlets.com/ http://java.sun.com/products/servlet/ http://www.apl.jhu.edu/~hall/java/Servlet-Tutorial/ JSP http://java.sun.com/products/jsp/ http://www.jsptut.com/ Source Code http://mobocracy.net/code/calculator