Hello World Model Project


In Chapter 4 we used a Hello World example that was contained in one file. The Hello World example in this chapter is more complex because it uses several classes.

This section explains the basic structure for all the buildfiles and directories you use in this example and the rest of the book. We introduce the three Java class files: a GreetingBean class, a GreetingFactory class, and a Greeting interface. Then, we discuss how to build these files with Ant and break down the Ant buildfiles ' target execution step by step. We also explain how to use the Ant command-line utility to build the files with Ant.

Overview of Model Classes

The GreetingFactory knows how to create a Greeting object. Here is the listing for the GreetingFactory:

 package xptoolkit.model; public class GreetingFactory {     private GreetingFactory(){}     public Greeting getGreeting()throws Exception {      String clazz = System.getProperty("Greeting.class",                              "xptoolkit.model.GreetingBean");         return (Greeting)Class.forName(clazz).newInstance();     }          public static GreetingFactory getGreetingFactory(){         return new GreetingFactory();     } } 

Next we have a Greeting interface that defines the contract of a Greeting objectthat is, what type of behavior it supports. The Greeting interface is as follows :

 package xptoolkit.model; public interface Greeting extends java.io.Serializable{     public String getGreeting(); } 

Finally, the GreetingBean class implements the Greeting Interface. GreetingBean is defined as follows:

 package xptoolkit.model; public class GreetingBean implements Greeting{     public GreetingBean(){}     public String getGreeting(){       return "Hello World!";     } } 

The GreetingBean returns the message Hello World! just like the message in the Chapter 4 application. To create a Greeting instance, you use the GreetingFactory. The default implementation of the GreetingFactory gets the implementation class from a property and instantiates an instance of that class with the Class.forName().newInstance() method. It casts the created instance to the Greeting interface.

These two lines of code create the Greeting instance from the GreetingFactory's getGreeting() method:

 String clazz = System.getProperty("Greeting.class",                              "xptoolkit.model.GreetingBean");       return (Greeting)Class.forName(clazz).newInstance(); 

Thus any class that implements the Greeting interface can be substituted as the Greeting.class system property. Then, when the class is instantiated with the factory's getGreeting() method, the application uses the new implementation of the Greeting interface.

We use this technique in Chapter 6 to add support for EJBs to the Web application seamlessly. We create an Ant script that can deploy the same Web application to use either enterprise beans or another bean implementation just by setting an Ant property. Later, we also map the Greeting interface with the use bean action of a JSP when we implement the Model 2 using servlets and JSP.

Creating a Project Directory Structure for Model

This part of the sample application uses the smallest buildfile. Basically, we just need to create a JAR file that acts as a common library. We don't need any special manifest file or deployment files. This is the most basic buildfile and directory structure you will see in this example. Here is the directory structure for the Model directory:

 Root of Model    build.xml +---src     +---xptoolkit         \---model                GreetingFactory.java                Greeting.java                GreetingBean.java 

Notice that there are only four files in the Model directory and subdirectories. Also notice that the name of the Ant file is build.xml. Remember from Chapter 4 that build.xml is the default buildfile; if Ant is run in this directory, it automatically finds build.xml without you having to specify it on the command line. Let's dig into the model buildfile.

Creating a Buildfile for a Shared Library

The model buildfile has six targets: setProps, init, clean, delete, prepare, compile, package, and all. The buildfiles in this example have similar targets:

  • setProps: Sets up the output directory ("outputdir") property if it is not already set. This behavior is important so we can easily set a different output directory from the command line or from another buildfile that invokes this buildfile, and yet have a reasonable default.

  • init: Initializes all the other properties relative to the "outputdir" property defined in the setProps target; init depends on setProps.

  • clean: Cleans up the output directories and the output JAR file.

  • prepare: Creates the output directories if they do not already exist.

  • compile: Compiles the Java source files for the model into the build directory defined in the init target.

  • package: Packages the compiled Java source into a JAR file.

  • all: Runs all the tags. It is the default target of this build project.

Analysis of the Model Project Buildfile

The following listing shows the entire buildfile for the model project. In this section we provide a step by step analysis of how this buildfile executes. All the buildfiles in the Hello World example are structured in a similar fashion, so understanding the model project's buildfile is essential to understanding the others. A quick note on naming conventions: As you see from the first line of code in the next listing, the project name for this buildfile is model. Thus we refer to this buildfile as the model project buildfile . This naming convention becomes essential once we begin dealing with the five other buildfiles in this project.

 <project name="model" default="all" >          <target name="setProps" unless="setProps"                            description="setup the properties.">         <property name="outdir" value="/tmp/app/" />      </target>     <target name="init" depends="setProps"                             description="initialize the properties.">         <tstamp/>         <property name="local_outdir" value="${outdir}/model" />         <property name="build" value="${local_outdir}/classes" />         <property name="lib" value="${outdir}/lib" />         <property name="model_jar" value="${lib}/greetmodel.jar" />     </target>     <target name="clean" depends="init"                      description="clean up the output directories and jar.">         <delete dir="${local_outdir}" />         <delete file="${model_jar}" />     </target>          <target name="prepare" depends="init"                            description="prepare the output directory.">         <mkdir dir="${build}" />         <mkdir dir="${lib}" />     </target>     <target name="compile" depends="prepare"                            description="compile the Java source.">         <javac srcdir="./src" destdir="${build}" />     </target>     <target name="package" depends="compile"                    description="package the Java classes into a jar.">         <jar jarfile="${model_jar}"            basedir="${build}" />     </target>          <target name="all" depends="clean,package"                     description="perform all targets."/>  </project> 

Let's go over the model project buildfile and each of its targets in the order they execute. First, the model project sets the all target as the default target, as follows:

 <project name="model" default="all" > 

The all target is executed by default, unless we specify another target as a command-line argument of Ant. The all target depends on the clean and package targets. The clean target depends on the init target. The init target depends on the setProps target, and thus the setProps target is executed first.

Following is the setProps target defined in build.xml:

 <target name="setProps" unless="setProps"                            description="setup the properties.">         <property name="outdir" value="/tmp/app/" />      </target> 

The setProps target executes only if the "setProps" property is not set (unless="setProps"). Thus, if a parent buildfile calls this buildfile, it can set the "setProps" property and override the value of outdir so that the setProps target of this file does not execute (we give an example of this later). If the setProps target executes, it sets the value of outdir to /tmp/app.

Next, the init target is executed. Following is the init target defined in build.xml:

 <target name="init" depends="setProps"                             description="initialize the properties.">         <tstamp/>         <property name="local_outdir" value="${outdir}/model" />         <property name="build" value="${local_outdir}/classes" />         <property name="lib" value="${outdir}/lib" />         <property name="model_jar" value="${lib}/greetmodel.jar" />     </target> 

The init target uses the tstamp task to get the current time, which is used by the javac task to see if a source file is out of data and needs to be compiled. The init target defines several properties that refer to directories and files needed to compile and deploy the model project. We will discuss the meaning of these properties because all the other buildfiles for this example use the same or similar properties. The init target defines the following properties:

  • The "local_outdir" property defines the output directory of all the model project's intermediate files (Java class files).

  • The "build" property defines the output directory of the Java class files.

  • The "lib" property defines the directory that holds the common code libraries (JAR files) used for the whole Model 2 Hello World example application.

  • The "model_jar" property defines the output JAR file for this project.

As a general rule, if you use the same literal twice, you should go ahead and define it in the init target. You don't know how many times we've shot ourselves in the foot by not following this rule. This buildfile is fairly simple, but the later ones are more complex. Please learn from our mistakes (and missing toes).

Now that all the clean target's dependencies have executed, the clean target can execute. The clean target deletes the intermediate files created by the compile and the output common JAR file, which is the output of this project. Here is the code for the clean target:

 <target name="clean" depends="init"               description="clean up the output directories and jar.">       <delete dir="${local_outdir}" />       <delete file="${model_jar}" />     </target> 

Remember that the all target depends on the clean and package targets. The clean branch and all its dependencies have now executed, so it is time to execute the package target branch (a branch is a target and all its dependencies). The package target depends on the compile target, the compile target depends on the prepare target, and the prepare target depends on the init target, which has already been executed.

Thus, the next target that executes is prepare, because all its dependencies have already executed. The prepare target creates the build output directory, which ensures that the lib directory is created. The prepare target is defined as follows:

 <target name="prepare" depends="init"                            description="prepare the output directory.">         <mkdir dir="${build}" />         <mkdir dir="${lib}" />     </target> 

The next target in the package target branch that executes is the compile targetanother dependency of the package target. The compile target compiles the code in the src directory to the build directory, which was defined by the "build" property in the init target. The compile target is defined as follows:

 <target name="compile" depends="prepare"                            description="compile the Java source.">         <javac srcdir="./src" destdir="${build}"/>      </target> 

Now that all the target dependencies of the package target have been executed, we can run the package target. Whew! The package target packages the Java classes created in the compile target into a JAR file that is created in the common lib directory. The package target is defined as follows:

 <target name="package" depends="compile"                    description="package the Java classes into a jar.">         <jar jarfile="${model_jar}"            basedir="${build}" />     </target> 

Running an Ant Buildfile

In this section, we discuss how to run the Hello World model project buildfile. There are three steps to running the Ant buildfile:

  1. Set up the environment.

  2. Go to the directory that contains the build.xml file for the model.

  3. Run Ant.

Successfully running the buildscript gives us the following output:

 Buildfile: build.xml setProps: init: clean: prepare:     [mkdir] Created dir: C:\tmp\app\model\classes compile:     [javac] Compiling 3 source files to C:\tmp\app\model\classes package:       [jar] Building jar: C:\tmp\app\lib\greetmodel.jar all: BUILD SUCCESSFUL Total time: 3 seconds 

If you do not get this output, check that the properties defined in the init target make sense for your environment. If you are on a Unix platform and the buildfile is not working, make sure that the /tmp directory exists and that you have the rights to access it. Alternatively, you could run the previous script by doing the following on the command line:

 $ ant -DsetProps=true -Doutdir=/usr/rick/tmp/app 

Basically, you want to output to a directory that you have access to, just in case you are not the administrator of your own box. If from some reason Ant still does not run, make sure you set up the Ant environment variables (refer to Chapter 4 for details).

After successfully running Ant, the output directory for the model project will look like this:

 Root of output directory \---app     +---lib            greetmodel.jar          \---model         \---classes             \---xptoolkit                 \---model                         GreetingFactory.class                         Greeting.class                         GreetingBean.class 

Notice that all the intermediate files to build the JAR file are in the model subdirectory. The output from this project is the greetmodel.jar file, which is in ${outdir}/app/lib. The next project, the application project, needs this JAR file in order to compile. In the next section, we discuss how to build a standalone Java application with Ant that uses the JAR file (greetmodel.jar) from the model project.




Professional Java Tools for Extreme Programming
Professional Java Tools for Extreme Programming: Ant, XDoclet, JUnit, Cactus, and Maven (Programmer to Programmer)
ISBN: 0764556177
EAN: 2147483647
Year: 2003
Pages: 228

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