Building The Application Framework
Okay, we've got the basic structure of our application set up. We've got all the tools we need spun out into the zdev directory, and we've built the directory structure our application will be developed in.
Breaking Down The App Directory Structure
As intimidating as all that directory structure looks, each directory (other than the obvious src and war directories) has a purpose in ending up with a web application. Let's go through each one as to what's in there. This is the step you're going to do after you download and install the 'stuff' and have created the above application directory structure.
-
ant: This is where all of your utility programs go to make building and deploying your war file simple. Since I'm not teaching any of this stuff, I'll just include the files in an appendix. If you're familiar with this stuff, you can easily map all of it to your application. If you have no clue about any of this, don't dispair. I'll show you how to fade all of this later, though not in much depth. It's all a hack so you'll be on your own as it's really only specific to tommycat. Anyway, the files you will find in here are as follows: cat.xml, catbuild.xml, custom.properties, setenv.bat, tomstart.bat, and tomstop.bat
-
archives: This is used by Ant and the build scripts cat.xml and catbuild.bat to store the catalog.jar and catalog.war files which are then swept up into tommycat. You'll see it's use in cat.xml, which is the build file for this project.
-
build: This is used by Ant and the build scripts cat.xml and catbuild.bat to create the com.pmr.cat directory structure containing the Java .class files and the jsp directory structure to hold all of the war directories .jsp files, i.e. war/catalog/cat.
-
compilelib: This is the application specific lib directory. Because our app is pretty simple, we really don't need any external .jar files to reference. Our CLASSPATH setting and our build file take care of grouping any .jar files we need into the war file. For example, because our app will use servlets, we're going to specifically need both the jsp-api.jar and servlet-api.jar files. I could download these from somewhere and stuff them into this directory, but instead I choose in my build file to use the ones in tommycat's lib directory. Don't worry about this stuff. When you go to compile your code or fire up tommycat, if something is missing, you'll know right away.
-
war/catalog/cat: This is where we will put our welcome.jsp file.
-
war/catalog/css: This is where we will put our catalog.css file.
-
war/META-INF: The file context.xml is a file that tells tommycat what context this application will be referenced by. It looks like this
<Context path="/catalog"
docBase="catalog"
reloadable="true"
userNameing="false"
privileged="true"
debug="0"
swallowOutput="false"/>
-
war/catalog/WEB-INF: This is where the web.xml file that we'll need to build will go. Create the following web.xml file and stick it into there:
<?xml version="1.0" encoding="ISO-8859-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>Catalog Application</display-name>
<description>Catalog Application</description>
<servlet>
<servlet-name>cat</servlet-name>
<servlet-class>com.pmr.cat.controller.CatAction</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cat</servlet-name>
<url-pattern>/cat</url-pattern>
</servlet-mapping>
</web-app>
Let's take a closer look at the guts of some of the files listed above.
ant
As I mentioned, there are a bunch of helpful files here in the ant directory. I'm going to list the content of each one mostly so you can see where the Java and jsp files you create are going to end up in tommycat, or in their corresponding locations in whatever webserver you are using.
setenv.bat
set ANT_HOME=\zdev\apache-ant-1.7.1
set CATALINA_HOME=\zdev\apache-tomcat-6.0.20
set JAVA_HOME=\zdev\Java\jdk1.6.0_17
set CATALINA_BASE=\zdev\apache-tomcat-6.0.20
set PATH=%PATH%;\zdev\apache-ant-1.7.1\bin
set CLASSPATH=%CLASSPATH%
Any build file or process that you use is going to need to know where the webserver is, where Ant itself sits (if you choose to use it), and what other objects are needed in the Java classpath. For example, at work I had to develop a web service client and we used Apache Axis to generate the objects in the .wsdl file from the web service server. All of these Axis files had to be referenced in the Java classpath.
custom.properties
tomcat.deploy.home=\\zdev\\apache-tomcat-6.0.20
tomcat.home=\\zdev\\apache-tomcat-6.0.20
dir.deploy=${tomcat.deploy.home}\\webapps
javaexec=\\zdev\\Java\\jdk1.6.0_17\\bin\\javac
javac.compiler=javac1.6
The custom.properties file is used by the application ant build file, cat.xml.
tomstart.bat, and tomstop.bat
\zdev\apache-tomcat-6.0.20\bin\startup.bat
and
\zdev\apache-tomcat-6.0.20\bin\shutdown.bat
These files will start and stop your local tommycat.
catbuild.xml
ant -f cat.xml deploy
This is the file you use to build and deploy your application. Notice that it references the build file cat.xml and the specific ant target action of 'deploy'. See cat.xml.
cat.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="main" default="init">
<property environment="env"/>
<property file="custom.properties"/>
<property name="projectname" value="catalog"/>
<property name="dir.root" value="../"/>
<property name="build.compiler" value="${javac.compiler}"/>
<property name="dir.lib" value="${dir.root}/compilelib"/>
<property name="dir.src" value="${dir.root}/src"/>
<!--property name="dir.utils.src" value="${dir.root}/../utils/src"/-->
<property name="dir.archives" value="${dir.root}/archives"/>
<property name="dir.build" value="${dir.root}/build"/>
<property name="dir.deploy" value="${tomcat.home}/webapps"/>
<property name="javac" value="${javaexec}"/>
<property name="dir.warbase" value="${dir.root}/war"/>
<property name="warfilename" value="${projectname}.war"/>
<property name="warcontext" value="${projectname}"/>
<property name="dir.jdk" value="${env.JAVA_HOME}/jre/lib"/>
<target name="init">
<echo message="${projectname}"/>
<echo message="${build.compiler}"/>
<echo message="${build.compiler.fulldepend}"/>
<echo message="${compileWithDebug}"/>
<echo message="${dir.root}"/>
<echo message="${dir.src}"/>
<!--echo message="${dir.utils.src}"/-->
<echo message="${dir.archives}"/>
<echo message="${dir.build}"/>
<echo message="${dir.lib}"/>
<echo message="${dir.deploy}"/>
<echo message="${dir.jdk}"/>
<echo message="${javac}"/>
<echo message="${dir.warbase}"/>
<echo message="${warfilename}"/>
<echo message="${warcontext}"/>
</target>
<target name="prepare" depends="init">
<mkdir dir="${dir.archives}"/>
<mkdir dir="${dir.build}"/>
</target>
<target name="reset">
<antcall target="prepare"/>
</target>
<path id="project.classpath">
<pathelement location="${dir.src}"/>
<fileset dir="${tomcat.home}/lib">
<include name="jsp-api.jar"/>
</fileset>
<fileset dir="${tomcat.home}/lib">
<include name="servlet-api.jar"/>
</fileset>
<fileset dir="${dir.lib}">
<include name="*.jar"/>
</fileset>
</path>
<target name="build_cat">
<delete file="${dir.archives}/${projectname}.jar"/>
<javac srcdir="${dir.src}"
includes="com/pmr/cat/**/*.*"
destdir="${dir.build}"
fork="yes"
executable="${javaexec}"
compiler="${build.compiler}"
deprecation="off">
<classpath refid="project.classpath"/>
</javac>
<antcall target="jar_cat"/>
</target>
<target name="build_war" depends="reset">
<delete file="${dir.archives}/${warfilename}"/>
<antcall target="build_cat"/>
<copy todir="${dir.build}/jsp/${projectname}">
<fileset dir="${dir.warbase}/${projectname}"
includes="**/*.jsp"/>
</copy>
<touch>
<fileset dir="${dir.build}/jsp/${projectname}"/>
</touch>
<war destfile="${dir.archives}/${warfilename}"
webxml="${dir.warbase}/${projectname}/WEB-INF/web.xml"
basedir="${dir.warbase}/${projectname}"
excludes="**/web.xml"
includes="${projectname}/**/*.*,**/*.jsp,css/*.css,
WEB-INF/lib/*.*,WEB-INF/*.*,
WEB-INF/classes/resources/*.*,
WEB-INF/classes/**/*.class,META-INF/context.xml">
<lib dir="${dir.lib}"
includes="*.jar"/>
<lib dir="${dir.archives}"
includes="${projectname}.jar"/>
</war>
<!--
COPY THE WAR TO ARCHIVES
-->
<copy todir="${dir.root}/../deploy/war">
<fileset dir="${dir.archives}"
includes="${warfilename}"/>
</copy>
</target>
<target name="jar_cat">
<jar jarfile="${dir.archives}/${projectname}.jar"
basedir="${dir.build}"
includes="com/pmr/cat/**/*.class"/>
</target>
<target name="deploy" depends="build_war">
<unwar src="${dir.archives}/${warfilename}"
dest="${dir.deploy}/${warcontext}"/>
</target>
</project>
The key here is to go to the target 'deploy' which is what's in the catbuild.bat command file and follow the bouncing ball through this cat.xml build file as to how the files are being compiled and where they are going. Of note is that this build file does not pre-compile the .jsp files. It just moves them up into tommycat's webapps. When the application calls one of these .jsp files, tommycat will compile it and move the resulting class file to where it needs to go.
Also note that I have named this file cat.xml. It should really be called build.xml. And, in fact, if it isn't called that in most containers, the webserver will have no idea what to do with the file. I named this cat.xml so that it is clear that we are not using some third party framework and that you will know exactly which file I am talking about when I reference cat.xml as there are so many possible build.xml files that float around in a web app that it can get you really confused. It did me. But then, maybe this will confuse you even more. I dunno. All I can do is try to make a clear distinction as to which file I am using. Just know that in the 'real world' you should name this thing build.xml.
Testing Tomcat
Before going any further, we need to test this framework for basic functionality. This first test will be to just see if we have tommycat running correctly.
I have a little batch file gocat.bat in my Windows classpath that takes me to the ant directory and executes the setenv.bat file to get my environment all set.
c:
cd C:\pmr\catalog\ant
setenv
Open a dos command window and type gocat at the prompt. It should leave you in the ant directory where you can now type: tomstart. If all is well, another dos window should pop up with tommycat humming away. If you get any errors, you have to fix them now or you'll never get the app running.
Now, open a browser and type http://localhost:8080/. If you get a welcome screen that proclaims 'If you're seeing this page via a web browser, it means you've setup Tomcat successfully. Congratulations!' then you are all hooked up and ready to start writing your application! If you don't get this message, you'll have to debug and fix.