Web Application Project


Web Application Project

The Web application is another subproject of the Model 2 Hello World application; it consists of a servlet, two JSPs, an HTML file, and a deployment descriptor. This section describes how to build a WAR file with a deployment descriptor. We also explain how to map servlets and JSPs to servlet elements in the deployment descriptor and how to map the servlet elements to URLs. In addition, this section breaks down the webapplication project buildfile step by step, and shows how to use the buildfile to build and deploy the Web application.

Web Application Project Directory Structure

The following are the files that we build into a Web application:

 Web application root directory    build.xml +---JSP       HelloWorld.jsp       HelloApplet.jsp +---src    \---xptoolkit       \---web              HelloWorldServlet.java +---HTML        index.html \---meta-data        web.xml 

Notice that the webapplication project includes only six files. There are four subdirectories: JSP, src, HTML, and meta-data, and the root directory holds the build.xml file. The JSP directory contains two JSPs: HelloWorld.jsp and HelloApplet.jsp. Under the src directory is the Java source for the servlet xptoolkit.web.HelloWorldServlet.java. The web.xml file under the meta-data directory holds the deployment file for this Web application.

HelloWorldServlet.java

The servlet is contained in the class xptoolkit.web.HelloWorldServlet (see the next listing). Like the Java application, it uses the Greeting interface and the GreetingFactory class that are packaged in greetmodel.jar, the output of the model project.

 package xptoolkit.web; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.servlet.ServletException; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.RequestDispatcher; /* import the classes to create a greeting object or type greeting */ import xptoolkit.model.GreetingFactory; import xptoolkit.model.Greeting; public class HelloWorldServlet extends  HttpServlet{          public void init(ServletConfig config) throws ServletException{         super.init(config);            /* Read in the greeting type that the factory should create */         String clazz = config.getInitParameter("Greeting.class") ;         if(clazz!=null)System.setProperty("Greeting.class",clazz);                   }               public void doGet(HttpServletRequest request,                                     HttpServletResponse response)                                             throws ServletException{         RequestDispatcher dispatch;         ServletContext context;        /*Get the session, create a greeting bean, map the greeting           bean in the session, and redirect to the Hello World JSP.        */         try {                                                                                      /* Create the greeting bean and map it to the session. */           HttpSession session = request.getSession(true);           Greeting greet = (Greeting)                GreetingFactory.getGreetingFactory().getGreeting();           session.setAttribute("greeting", greet);                              /* Redirect to the HelloWorld.jsp */            context = getServletContext();            dispatch = context.getRequestDispatcher("/HelloWorldJSP");            dispatch.forward(request, response);         }catch(Exception e){             throw new ServletException(e);         }     }           /* Just call the doGet method */     public void doPost(HttpServletRequest request,                                      HttpServletResponse response)                                             throws ServletException{         doGet(request, response);     }      } 

Analyzing HelloWorldServlet

HelloWorldServlet is a simple servlet; it reads in the servlet initialization parameters in the init() method, as follows :

 String clazz = config.getInitParameter("Greeting.class") ; 

It uses the value of the initialization parameter "Greeting.class" to set the System property "Greeting.class", as follows:

 System.setProperty("Greeting.class",clazz); 

You will recall from Chapter 5 that the GreetingFactory uses the system property "Greeting.class" to decide which implementation of the Greeting interface to load. Now let's get to the real action: the doGet() and doPost() methods .

When the doGet() or doPost() method of the HelloWorldServlet is called, the servlet uses the GreetingFactory to create a greeting as follows:

 Greeting greet = (Greeting)                 GreetingFactory.getGreetingFactory().getGreeting(); 

The HelloWorldServlet then maps the greeting object into the current session (javax.servlet.http .HttpSession) under the name "greeting", as follows:

 session.setAttribute("greeting", greet); 

Finally, the HelloWorldServlet forwards processing of this request to the JSP file HelloWorld.jsp by getting the request dispatcher for the HelloWorldServlet from the servlet's context, as follows:

 /* Redirect to the HelloWorld.jsp */            context = getServletContext();            dispatch = context.getRequestDispatcher("/HelloWorldJSP");            dispatch.forward(request, response); 

You may notice that the context.getRequestDispatcher call looks a little weird. This is the case because HelloWorld.jsp is mapped to /HelloWorldJSP in the deployment descriptor for the servlet. (We will discuss the deployment descriptor later.) Next, let's examine HelloWorld.jsp.

HelloWorld.jsp

HelloWorld.jsp exists to show the world the message it gets from the Greeting reference that the HelloWorldServlet mapped into session. The HelloWorld.jsp code is as follows:

 <jsp:useBean id="greeting" type="xptoolkit.model.Greeting"                                              scope="session"/> <html> <head> <title>Hello World</title> </head> <body> <h1><%=greeting.getGreeting()%></h1> </body> 

If you are a Web designer at heart, we understand if you are shocked and horrified by this HTML code. But for a moment, let's focus on the following two lines of code from the JSP:

 <jsp:useBean id="greeting" type="xptoolkit.model.Greeting"                                               scope="session"/> <h1><%=greeting.getGreeting()%></h1> 

Notice that the jsp:useBean action grabs the greeting reference that we put into the session with the HelloWorldServlet. Then, we print out the greeting with the JSP scriptlet expression <%=greeting.getGreeting()%>.

This sums up what the Model 2 Hello World Web application does. We will discuss the other JSP, HelloApplet.jsp, after we examine the applet subproject. For now, the next section explains why the servlet could forward HelloWorldJSP to the JSP HelloWorld.jsp.

Deployment Descriptor for the HelloWorld Web Application

In order to configure the JSPs and servlets, we need a deployment descriptor. The following code defines a simple deployment descriptor that assigns names and mappings to the JSPs and servlet. Please note that the deployment descriptor goes in the web.xml file:

 <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app   PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"   "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> <web-app>     <error-page>         <error-code>404</error-code>         <location>/HelloWorldServlet</location>     </error-page>     <servlet>         <servlet-name>HelloWorldServlet</servlet-name>         <servlet-class>xptoolkit.web.HelloWorldServlet</servlet-class>         <init-param>           <param-name>Greeting.class</param-name>           <param-value>@Greeting.class@</param-value>         </init-param>     </servlet>     <servlet>         <servlet-name>HelloWorldJSP</servlet-name>         <jsp-file>HelloWorld.jsp</jsp-file>     </servlet>     <servlet-mapping>         <servlet-name>HelloWorldServlet</servlet-name>         <url-pattern>/HelloWorldServlet</url-pattern>     </servlet-mapping>     <servlet-mapping>         <servlet-name>HelloWorldJSP</servlet-name>         <url-pattern>/HelloWorldJSP</url-pattern>     </servlet-mapping> </web-app> 

The deployment descriptor defines two servlet elements, one for the HelloWorldServlet and one for the HelloWorldJSP. If you are wondering why there is a servlet element for the HelloWorldJSP, remember that HelloWorld.jsp is compiled to a servlet before it is used for the first time. The HelloWorldServlet servlet element maps to the servlet (<servlet-class>xptoolkit.web.HelloWorldServlet</servlet-class>). The HelloWorldJSP element maps to the JSP file HelloWorld.jsp (<jsp-file>HelloWorld.jsp</jsp-file>). Then, the servlet mapping elements map the servlet element to specific URL patterns.

Thus HelloWorldServlet maps to /HelloWorldServlet (<url-pattern>/HelloWorldServlet</url-pattern>); this is relative to the Web application location from the root of the server. And, the HelloWorldJSP servlet element is mapped to the /HelloWorldJSP URL pattern (<url-pattern>/HelloWorldJSP</url-pattern>).

The buildfile must deploy the descriptor to a place where the application server can find it. It does this by packaging the HTML files, JSP files, Java servlet, and deployment descriptor in a WAR file. The next section describes the buildfile for this project.

Buildfile for the HelloWorld Web Application

This project has many more components than the other subprojects . As you would expect, the webapplication project buildfile (see the next listing) is much more complex, but it builds on the foundation set by the model projectthat is, the webapplication project buildfile has the same base targets with the same meanings: setProps, init, clean, delete, prepare, mkdir, compile, package, and all.

To the base targets, the webapplication project's buildfile adds the prepare_metadata and deploy targets. The prepare_metadata target sets up the Ant filtering for the deployment descriptor (we talk about this in detail towards the end of this section). The deploy target adds the ability to deploy to both Resin and Tomcat Web application servers. The remaining details of this buildfile are covered in the applet and the enterprise beans sections later in this chapter.

 <project name="webapplication" default="all" >          <target name="setProps" unless="setProps"                            description="setup the properites.">         <property name="outdir" value="/tmp/app" />       </target>          <target name="init" depends="setProps"                             description="initialize the properties.">       <tstamp/>       <property name="local_outdir" value="${outdir}/webapps" />       <property name="lib" value="${outdir}/lib" />       <property name="dist" value="${outdir}/dist" />       <property name="build" value="${local_outdir}/webclasses" />       <property name="meta" value="${local_outdir}/meta" />       <property name="deploy_resin" value="/resin/webapps" />       <property name="deploy_tomcat" value="/tomcat/webapps" />       <property name="build_lib" value="./../lib" />       <property name="jsdk_lib" value="/resin/lib" />     </target>        <target name="clean_deploy" >         <delete file="${deploy_resin}/hello.war" />         <delete dir="${deploy_resin}/hello" />         <delete file="${deploy_tomcat}/hello.war" />         <delete dir="${deploy_tomcat}/hello" />     </target>     <target name="clean" depends="init,clean_deploy"                            description="clean up the output directories.">         <delete dir="${local_outdir}" />         <delete file="${dist}/hello.war" />     </target>          <target name="prepare" depends="init"                            description="prepare the output directory.">         <mkdir dir="${build}" />         <mkdir dir="${dist}" />         <mkdir dir="${build_lib}" />      </target>          <target name="compile" depends="prepare"                            description="compile the Java source.">         <javac srcdir="./src" destdir="${build}">             <classpath >                 <fileset dir="${lib}">                     <include name="**/*.jar"/>                 </fileset>                 <fileset dir="${jsdk_lib}">                      <include name="**/*.jar"/>                 </fileset>                          <fileset dir="${build_lib}">                     <include name="**/*.jar"/>                 </fileset>             </classpath>         </javac>     </target>     <target name="prepare_meta_ejb" if="ejb">         <filter token="Greeting.class"                value="xptoolkit.model.GreetingShadow"/>     </target>     <target name="prepare_meta_noejb" unless="ejb">         <filter token="Greeting.class"                  value="xptoolkit.model.GreetingBean"/>     </target>              <target name="prepare_meta"              depends="prepare_meta_ejb, prepare_meta_noejb">         <copy todir="${meta}" filtering="true">             <fileset dir="./meta-data"/>         </copy>     </target>     <target name="package" depends="compile">                  <mkdir dir="${meta}" />         <antcall target="prepare_meta" />         <war warfile="${dist}/hello.war" webxml="${meta}/web.xml">             <!--                  Include the html and jsp files.                  Put the classes from the build into the classes directory                  of the war.             /-->         <fileset dir="./HTML" />         <fileset dir="./JSP" />           <classes dir="${build}" />                          <!-- Include the applet. /-->           <fileset dir="${lib}" includes="helloapplet.jar" />        <!-- Include all of the jar files except the ejbeans and applet.              The other build files that create jars have to be run in the             correct order. This is covered later.   /-->         <lib dir="${lib}" >             <exclude name="greet-ejbs.jar"/>             <exclude name="helloapplet.jar"/>           </lib>         </war>    </target>     <target name="deploy" depends="package">         <copy file="${dist}/hello.war" todir="${deploy_resin}" />                      <copy file="${dist}/hello.war" todir="${deploy_tomcat}" />                          </target>          <target name="all" depends="clean,package"                            description="perform all targets."/>  </project> 

The final output of the Web application project is a single WAR file. The WAR file is built (not surprisingly) by the package target. Here is the listing for the package target:

 <target name="package" depends="compile">                  <mkdir dir="${meta}" />         <antcall target="prepare_meta" />         <war warfile="${dist}/hello.war" webxml="${meta}/web.xml">             <!--                  Include the html and jsp files.                  Put the classes from the build into the classes directory                  of the war.             /-->            <fileset dir="./HTML" />            <fileset dir="./JSP" />            <classes dir="${build}" />                          <!-- Include the applet. /-->             <fileset dir="${lib}" includes="helloapplet.jar" />             <!-- Include all of the jar files except the ejbeans  and applet.   /-->             <lib dir="${lib}" />         </war>    </target> 

As you can see, this package target is much larger than the other two we've discussed (model and application). For now we'll defer a detailed discussion of the second and third lines of code:

 <mkdir dir="${meta}" />         <antcall target="prepare_meta" /> 

These lines do some processing on the web.xml deployment descriptor file and put the file in the directory defined by ${meta} directory (note that the "meta" property is set in the init target). We explain the processing done to the deployment descriptor in the section "Enterprise JavaBeans" found later in this chapter. Next, the package target calls the war task, which is as follows:

 <war warfile="${dist}/hello.war" webxml="${meta}/web.xml">            <fileset dir="./HTML" />            <fileset dir="./JSP" />            <classes dir="${build}" />            <fileset dir="${lib}" includes="helloapplet.jar" />            <lib dir="${lib}" />         </war> 

The WAR file hello.war is put in the distribution directory (dist), which is specified by the war task's "warfile" attribute (warfile="${dist}/hello.war"). The dist directory is another common directory that is used by the main project's buildfile later to build an enterprise archive (EAR) file; the "dist" property is defined in the init target. The "webxml" attribute of the war task defines the deployment descriptor to use; it's the one we processed at the beginning of the package target. The web.xml file is put in the WAR file's WEB-INF/ directory.

In addition, the war task body specifies three file sets. One file set includes the helloapplet.jar file (which we discuss in the section "HelloWorld.jsp Applet Delivery" later in this chapter) and all the files in the HTML and JSP directories. The war task body also specifies where to locate the classes using <classes dir="${build}" />. This command puts the classes in the WEB-INF/classes directory.

The webapplication project's buildfile defines a slightly more complex compile target, as follows:

 <target name="compile" depends="prepare"                            description="compile the Java source.">         <javac srcdir="./src" destdir="${build}">             <classpath >                 <fileset dir="${lib}">                     <include name="**/*.jar"/>                 </fileset>                          <fileset dir="${build_lib}">                     <include name="**/*.jar"/>                 </fileset>             </classpath>         </javac>     </target> 

Notice that this compile target defines two file sets. One file set (<fileset dir="${build_lib}">) is used to include the classes needed for servlets (such as import javax.servlet.*). The other file set (<fileset dir="${lib}">) is used to include the Greeting interfaces and the GreetingFactory class. The only real difference from the application compile target is the inclusion of the JAR file for servlets. The "build_lib" property is defined in the webapplication project's init target, as follows:

 <property name="build_lib" value="./../lib" /> 

The good thing about this approach is that if we need additional JAR files, we can put them in the build_lib. The second file set (<fileset dir="${build_lib}">) grabs all the JAR files in the ./../lib directory.

The webapplication project's buildfile adds a few convenience targets geared toward Web applications. The deploy target copies the WAR file that this buildfile generates to the webapps directory of Tomcat and Resin. (Tomcat is the reference implementation servlet engine of the Java specification. Resin is an easy-to-use Java application server that supports JSPs, EJBs, J2EE container specification, XSL, and so on.) Without further ado, here is the deploy target:

 <target name="deploy" depends="package">         <copy file="${dist}/hello.war" todir="${deploy_resin}" />         <copy file="${dist}/hello.war" todir="${deploy_tomcat}" /> </target> 

Both Tomcat and Resin pick up the WAR files automatically, in the interest of doing no harm and cleaning up after ourselves . The webapplication project's buildfile also adds an extra clean_deploy target that deletes the WAR file it deployed and cleans up the generated directory, as follows:

 <target name="clean_deploy" >         <delete file="${deploy_resin}/hello.war" />         <delete dir="${deploy_resin}/hello" />         <delete file="${deploy_tomcat}/hello.war" />         <delete dir="${deploy_tomcat}/hello" />     </target> 

"Great," you say. "But what if the application server I am deploying to is on another server that is half way around the world?" No problem; use the following FTP task:

 <ftp server="ftp.texas.austin.building7.eblox.org"        remotedir="/deploy/resin/webapps"        userid="kingJon"        password="killMyLandLord"        depends="yes"        binary="yes" >     <fileset dir="${dist}">       <include name="**/*.war"/>     </fileset>   </ftp> 

Building and Deploying the Web Application

This section explains how to build and deploy the Web application. The buildfile assumes that you have Resin and Tomcat installed in the root of your drive. You may need to make adjustments to the buildfile if you installed Resin or Tomcat in another directory or if you are using another J2EE-compliant Web application server.

To build the Web application, follow these steps:

  1. Navigate to the WebApplication directory, set up the environment, and then do the following at the command line:

     C:\CVS\...\MVCHelloWorld\WebApplication>ant 

    You will get the following output:

     Buildfile: build.xml setProps: init: clean_deploy:    [delete] Could not find file C:\resin\webapps\hello.war to delete.    [delete] Could not find file C:\tomcat\webapps\hello.war to delete clean:    [delete] Could not find file C:\tmp\app\dist\hello.war to delete. prepare:     [mkdir] Created dir: C:\tmp\app\webapps\webclasses     [mkdir] Created dir: C:\tmp\app\dist compile:     [javac] Compiling 1 source file to C:\tmp\app\webapps\webclasses package:     [mkdir] Created dir: C:\tmp\app\webapps\meta prepare_meta_ejb: prepare_meta_noejb: prepare_meta:      [copy] Copying 1 file to C:\tmp\app\webapps\meta       [war] Building war: C:\tmp\app\dist\hello.war all: BUILD SUCCESSFUL 
  2. Deploy the WAR files to the application server. If you install Resin or Tomcat off the root directory, then you can run the deploy target. Otherwise, modify the appropriate deploy properties defined in the init target. To deploy the application with Ant, do the following:

     C:\CVS\?.\MVCHelloWorld\WebApplication>ant deploy Buildfile: build.xml ...  ... deploy:      [copy] Copying 1 file to C:\resin\webapps      [copy] Copying 1 file to C:\tomcat\webapps BUILD SUCCESSFUL Total time: 0 seconds 
  3. After we run the application, we start Resin or Tomcat, and then hit the site with our browser. (More on this subject later.) We can also clean out the directories when we are ready to deploy a new version, as follows:

     C:\CVS\...\MVCHelloWorld\WebApplication>ant clean 

    The output looks like the following:

     Buildfile: build.xml setProps: init: clean_deploy:    [delete] Deleting: C:\resin\webapps\hello.war    [delete] Deleting: C:\tomcat\webapps\hello.war clean:    [delete] Deleting directory C:\tmp\app\webapps    [delete] Deleting: C:\tmp\app\dist\hello.war BUILD SUCCESSFUL Total time: 0 seconds 

    Notice that we delete the WAR files and the deployment directories. This is just good house-cleaning for when we do a build and deploy . In the next section, we will run the webapplication project.

Running the Web Application

Now that we've built and deployed the webapplication project, let's run it. We start our servlet engine and then open the site in our browserfor example, http://localhost/hello/HelloWorldServlet . (Resin's default setup is port 8080, so you may have to adjust the URL.) Here is what the Web application looks like when it's running:

click to expand

You may notice a couple of things. The application URL is defined in a directory called hello ( http:// localhost/hello/HelloWorldServlet ). By default, Tomcat and Resin unjar our WAR file in a directory called < War file File Name >. Later, we will use the EAR file to override this default behavior in a neutral application server way.

The HelloWorldServlet part of the application's URL is defined by a mapping in the deployment descriptor as follows:

 <servlet>         <servlet-name>HelloWorldServlet</servlet-name>         <servlet-class>xptoolkit.web.HelloWorldServlet</servlet-class>         <init-param>           <param-name>Greeting.class</param-name>           <param-value>@Greeting.class@</param-value>         </init-param>     </servlet>     <servlet-mapping>         <servlet-name>HelloWorldServlet</servlet-name>         <url-pattern>/HelloWorldServlet</url-pattern>     </servlet-mapping> 

The servlet tag declares the servlet and gives it a name. The servlet mapping assigns the HelloWorldServlet the URL pattern /HelloWorldServlet. We could change the URL pattern to /PeanutButter, and the URL http://localhost/hello/PeanutButter would work:

click to expand

Actually, we mapped the 404 error to HelloWorldServlet as well, so the server sends any URL it does not recognize to HelloWorldServlet to process (for the benefit of people with fumble fingers).

The next section describes a simple applet project that integrates with the webapplication project. Then, we will discuss Enterprise JavaBean deployment and enterprise archive files.

HelloWorld.jsp Applet Delivery

Now the applets JAR we built in Chapter 5 becomes part of the Web application. It is put in the Web application where the browser can find it. The Web application has a JSP page, HelloApplet.jsp, which has a jsp:plugin tag that delivers the applet to the browser. The HelloApplet.jsp with the jsp:plugin action is listed as follows:

 <html> <head><title>Hello World Applet</title></head> <body> <jsp:plugin type="applet"              code="xptoolkit.applet.HelloWorldApplet"              archive="helloapplet.jar"             height="200"             width="200"             align="center">     <jsp:fallback>      <!-- This fallback message will display if the plugin does not work. /-->         <p> Java is cool. Get a browser that supports the plugin. </ br>             Or we will hunt you down and melt your computer!         </p>     </jsp:fallback> </jsp:plugin> </body> </html> 

This shows how the applet is delivered to the browser. How is the applet included in the Web application's WAR file in the first place? We explain in the next section.

Including an Applet in a WAR File

If you look at the webapplication project buildfile, you will note that the war task in the package target does the following:

 <war warfile="${dist}/hello.war" webxml="${meta}/web.xml">            <fileset dir="./HTML" />            <fileset dir="./JSP" />            <classes dir="${build}" />            <fileset dir="${lib}" includes="helloapplet.jar" />            <lib dir="${lib}" />      </war> 

The fileset directive

 <fileset dir="${lib}" includes="helloapplet.jar" /> 

tells the war task to include only the helloapplet.jar file from the lib directory. Because this file set is not a classes- or lib-type file set, helloapplet.jar goes to the root of the WAR file. In contrast, the special lib and classes file sets put their files in WEB-INF/lib and WEB-INF/classes, respectively. The end effect is that the browser is able to get the applet.

After we build the applet, we go back and rebuild the Web application and then deploy it. We run Ant in the root of both the projects' home directories (if you get a compile error, be sure you have built the model, because the Web application depends on it). After everything compiles and the appropriate JAR and WAR files are built, we deploy the webapplication project by using the deploy target of the webapplication buildfile. Then we run the applet, as demonstrated in the following figure.

click to expand

It's important to recap what we have done. We created a common Java library called model.jar. This model.jar is used by a Web application and a regular Java application that is a standalone executable Java application in an executable JAR file. We create an applet that is loaded with a JSP page that has the jsp:plugin action. Once the applet loads into the browser, the applet communicates over HTTP to the Web application's HelloWorldServlet. HelloWorldServlet calls the getGreeting() method on the GreetingFactory, which is contained in the model.jar file.

In the next section, we set up the GreetingFactory so that it talks to an enterprise session bean that in turn talks to an enterprise entity bean. The Web application buildfile is set up so that after we add one property file, it can talk to either the enterprise beans or to the local implementation in the model library.




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