Ahora procederemos a trav�s del ciclo de desarrollo utilizando HttpUnit. Empieza con la idea de construir un list�n de tel�fonos electr�nico. Tu primer paso de implementaci�n (es decir, la parte que va despu�s de la solicitaci�n de requerimientos y del dise�o de la aplicaci�n) deber�a ser crear el �rbol de directorios y escribir un fichero build.xml fundacional para poder empezar a codificar y testear.
Primero, borra el �rbol de directorios phonelist y el archivo phonelist.tgz con los siguientes comandos:
rm -fr ~/projects/phonelist rm -f ~/phonelist.tgz
Ahora est�mos en el mismo punto como si acabaramos de empezar un proyecto de software. Crea el �rbol de directorios para contener los ficheros que crearemos con los siguientes comandos:
mkdir ~/projects/phonelist cd ~/projects/phonelist mkdir src mkdir src/web mkdir src/WEB-INF mkdir src/WEB-INF/classes mkdir src/WEB-INF/classes/com mkdir src/WEB-INF/classes/com/abcinc mkdir src/WEB-INF/classes/com/abcinc/phonelist mkdir src/test mkdir src/test/com mkdir src/test/com/abcinc mkdir src/test/com/abcinc/phonelist mkdir src/test/com/abcinc/phonelist/test
El siguiente paso es crear un fichero build.xml rudimentario que podamos desarrollar de forma incremental y probar con simples comandos de una l�nea que realicen la construcci�n y testeos autom�ticos. Teclea lo siguiente en un fichero llamado build.xml en el directorio ~/projects/phonelist:
<project name="Phone List Application" basedir="."> <target name="init"> <property name="tomcat.install.dir" value="/home/wchao/packages/jakarta-tomcat-4.1.27"/> <property name="struts.install.dir" value="/home/wchao/packages/jakarta-struts-1.1"/> <property name="src.dir" value="${basedir}/src"/> <property name="build.dir" value="${basedir}/build"/> <property name="war.base.name" value="phonelist"/> <property name="deploy.dir" value="${tomcat.install.dir}/webapps"/> <path id="base.path"> <fileset dir="${tomcat.install.dir}/common/lib"> <include name="*.jar"/> </fileset> <fileset dir="${struts.install.dir}/lib"> <include name="*.jar"/> </fileset> </path> <property name="classpath" refid="base.path"/> </target> </project>
Asegurate de cambiar los valores de las propiedades tomcat.install.dir y struts.install.dir para que reflejen las localizaciones adecuadas de Tomcat y Struts. Graba lo que tienes ahora. Acabas de teclear un target de inicializaci�n (target, como podr�as recordar, es un t�rmino de Ant para indicar una serie de instrucciones relacionadas empaquetadas como una unidad). El taget init define las propiedades que utilizar�s m�s adelante, como la localizaci�n de Tomcat, la localizaci�n de librer�as externas y la localizaci�n de los ficheros fuente.
�Definir Targets para tu Aplicaci�n Web
Ahora define algunos targets Ant que realmente realicen acciones. Para una aplicaci�n Web, como m�nimo deberias poder realizar estas dos tareas:
- Limpiar el directorio, borrando cualquier fichero compilado o copiado para poder empezar de nuevo s�lo desde el c�digo fuente.
- Compilar y desplegar la aplicaci�n en el Servidor Web (Tomcat en este caso).
La primera tarea que definir�s en build.xml es un target llamado clean que limpiar� el �rbol de directorios para empezar una construcci�n desde cero. La segunda tarea que definir�s ser� el target llamado deploy que compilar� las clases, empaquetar� las clases junto con otros ficheros Web y los descriptores en un fichero WAR, y luego desplegar� el fichero WAR en el servidor Web. Adem�s definir�s una tercera tarea llamada package-war que compilar� todas las clases y las empaquetar� junto a los ficheros Web no procesados (JSP, im�genes, ficheros de propiedades, etc.) en un fichero WAR que se puede desplegar en el directorio de despliegue de Tomcat (normalmente llamado webapps en las distribuciones est�ndar de Tomcat). El target package-war solo hace visibles y p�blicos los pasos intermedios de compilar y empaquetar los ficheros en un fichero WAR. El target deploy termina llamando al target package-war.
El target clean es bastante sencillo de codificar. Situa el siguiente fragmento de XML directamente despu�s de la etiqueta </target> que cierra el elemento <target name="init"> pero antes de la etiqueta de cierre </project>:
<target name="clean" depends="init" description="Clean build directory tree"> <delete dir="${build.dir}"/> </target>
El target deploy es m�s complicado, por eso lo vamos a dividir en varios pasos. Necesita hacer lo siguiente:
- Compilar los servlets y otras clases Java.
- Ensamblar las clases compiladas y los ficheros no procesados (como JSPs, im�genes, hojas de estilo, y descriptores de despliegue XML) en un fichero WAR.
- Desplegar la aplicaci�n copiando el fichero WAR en el directorio de Tomcat.
Compilar las clases Java y luego ensamblarlas con los ficheros no procesados en un fichero WAR se puede agrupar l�gicamente en un target package-war. Los usuarios podr�n invocar directamente este target desde Ant.
Una buena forma de imaginar qu� targets deber�as crear es trabajar hacia atr�s desde tu objetivo. Tu quieres desplegar un fichero WAR en Tomcat, eso significa que necesitas un fichero WAR con todos los ficheros de la aplicaci�n empaquetados. La forma m�s f�cil de crear un fichero WAR es comprimir un �rbol de directorios con la distribuci�n de ficheros que corresponda con el fichero WAR deseado. Recuerda que un fichero WAR simplemente es un fichero ZIP con una reglas espec�ficas sobre qu� ficheros necesitan estar presentes y d�nde deber�an ir ciertos ficheros en el �rbol de directorios. Para crear el �rbol de directorios con la distribuci�n descomprimida y el contenido de ficheros, sigue estos pasos:
- Consfigura los directorios para tener un lugar donde poner los ficheros.
- Copia los ficheros que no necesitan procesamiento en el �rbol de directorios descomprimido. Esto imcluir� las p�ginas JSP, los ficheros descritpores XML, las im�genes y otros tipos MIME.
- Compila las clases. El c�digo final se graba directamente en el �rbol de directorios descomprimido.
Para configurar los directorios, introduce el siguiente fragmento en build.xml debajo del target clean que acabas de crear:
<target name="create-unpacked-layout-dirs" depends="init"> <mkdir dir="${build.dir}/unpacked-layout"/> <mkdir dir="${build.dir}/unpacked-layout/WEB-INF"/> <mkdir dir="${build.dir}/unpacked-layout/WEB-INF/classes"/> <mkdir dir="${build.dir}/unpacked-layout/WEB-INF/lib"/> </target>
Todas las JSPs, las im�genes, las hojas de estilo y otros ficheros que no necesitan compilaci�n van directamente en el directorio unpacked-layout. Los descriptores de despliegue van en unpacked-layout/WEB-INF. Los ficheros de clases Java van en unpacked-layout/WEB-INF/classes. Los ficheros JAR de tus librer�as van en unpacked-layout/WEB-INF/lib.
El siguiente paso es copiar los ficheros que no necesitan compilaci�n en el �rbol unpacked-layout. Teclea lo siguiente en build.xml debajo del target create-unpacked-layout-dirs:
<target name="copy-unprocessed-files" depends="init, create-unpacked-layout-dirs"> <copy todir="${build.dir}/unpacked-layout"> <fileset dir="${src.dir}/web"> <include name="**"/> </fileset> </copy> <copy todir="${build.dir}/unpacked-layout/WEB-INF"> <fileset dir="${src.dir}/WEB-INF"> <exclude name="classes/**"/> <include name="**"/> </fileset> <fileset dir="${struts.install.dir}/lib"> <include name="*.tld"/> <include name="*.xml"/> </fileset> </copy> <copy todir="${build.dir}/unpacked-layout/WEB-INF"> <fileset dir="${src.dir}/WEB-INF"> <include name="classes/**/*.properties"/> </fileset> <fileset dir="${src.dir}/WEB-INF"> <include name="classes/**/*.xml"/> </fileset> </copy> <copy todir="${build.dir}/unpacked-layout/WEB-INF/lib"> <fileset dir="${struts.install.dir}/lib"> <include name="*.jar"/> </fileset> </copy> </target>
Este target primero copia los ficheros Web como p�ginas JSP directamente en unpacked-layout, luego copia los descriptores XML en unpacked-layout/WEB-INF. Despu�s de esto, copia las propiedades, recursos y otros ficheros de recursos dentro de unpacked-layout/WEB-INF/classes, y por �ltimo copia los ficheros JAR en unpacked-layout/WEB-INF/lib.
Ahora volvamos a los ficheros que requieren compilaci�n. A�ade el siguiente fragmento de c�digo XML a build.xml despu�s del target copy-unprocessed-files:
<target name="compile-classes" depends="init, create-unpacked-layout-dirs"> <javac destdir="${build.dir}/unpacked-layout/WEB-INF/classes" debug="on" deprecation="on" optimize="off" source="1.4"> <src path="${src.dir}/WEB-INF/classes"/> <classpath path="${classpath}"/> </javac> </target>
Este target compila todas las clases del directorio WEB-INF/classes del �rbol de c�digo fuente. Recuerda que la localizaci�n del �rbol de c�digo fuente se especific� en el target init. La localizaci�n se situ� en una propiedad global llamada src.dir. El compilador utiliza el classpath especificado en el target init. Los ficheros compilados se sit�an en el directorio unpacked-layout/WEB-INF/classes.
�Agrupar los Targets
Crea un nuevo target que agrupe los tres que acabas de crear. El nuevo target se llamar� build-unpacked, y es muy corto. Introduce el siguiente c�digo bajo el target compile-classes:
<target name="build-unpacked" depends="init, create-unpacked-layout-dirs, copy-unprocessed-files, compile-classes"/>
El target est� vac�o. S�lo invoca al target init para inicializar las propiedades y a los otros tres targets que acabas de crear. Ahora tienes la habilidad de construir toda la aplicaci�n y distribuir los ficheros seg�n ordena el est�ndar WAR.
El siguiente paso obvio es convertir la distribuci�n descomprimida en un WAR antes de desplegar el WAR en Tomcat. El siguiente fragmento de build.xml crea un directorio donde situar el fichero WAR:
<target name="create-deploy-dir" depends="init"> <mkdir dir="${build.dir}/deploy"/> </target>
Deber�as introducir este targer justo despu�s del target build-unpacked que acabas de crear. Ahora tienes una distribuci�n descomprimida de ficheros y un lugar para almacenar el fichero WAR.
El siguiente paso es crear el fichero WAR. Los ficheros WAR deben adherirse a una distribuci�n definida. Pon el siguiente fragmento de c�digo XML en build.xml justo despu�s del target create-deploy-dir:
<target name="package-war" depends="init, build-unpacked, create-deploy-dir" description="Build all the files and package them into a WAR file"> <war warfile="${build.dir}/deploy/${war.base.name}.war" webxml="${build.dir}/unpacked-layout/WEB-INF/web.xml"> <webinf dir="${build.dir}/unpacked-layout/WEB-INF"> <include name="**"/> <exclude name="web.xml"/> <exclude name="classes/**"/> <exclude name="lib/**"/> </webinf> <classes dir="${build.dir}/unpacked-layout/WEB-INF/classes"> <include name="**"/> </classes> <lib dir="${build.dir}/unpacked-layout/WEB-INF/lib"> <include name="**"/> </lib> <fileset dir="${build.dir}/unpacked-layout"> <include name="**"/> <exclude name="WEB-INF/**"/> </fileset> </war> </target>
Este target hace uso del target build-unpacked para crear la distribuci�n descomprimida y el target create-deploy-dir para crear el directorio para el fichero WAR. El propio target package-war s�lo tiene una instrucci�n: war, que crea un fichero WAR y especifica la localizaci�n del directorio WEB-INF, el directorio classes, el directorio lib, y los ficheros no procesados. En este punto tenemos la habilidad de generar un fichero WAR capaz de ser desplegado en Tomcat.
El siguiente paso es copiar el fichero en el directorio de despliegue de Tomcat para que �ste pueda desplegar la aplicaci�n. El siguiente fragmento XML copia el fichero WAR en el directorio de despliegue de Tomcat:
<target name="copy-war" depends="package-war"> <copy file="${build.dir}/deploy/${war.base.name}.war" todir="${deploy.dir}"/> </target>
Introduce el target copy-war justo despu�s del target package-war. Para unir estos dos targets en una funci�n de despligue �til, crea otro target que simplemente llame al target package-war seguido por el target copy-war. LL�malo deploy. Teclea lo siguiente en el fichero build.xml despu�s del target copy-war:
<target name="deploy" depends="package-war, copy-war" description="Deploy application to Tomcat"/>
El target deploy no contiene ninguna instrucci�n real. Simplemente llama a otros targets para relizar el trabajo.
Deber�as crear un target undeploy para poder eliminar una vieja versi�n de la aplicaci�n phonelist antes de desplegar una nueva version que resulte de los cambios que puedas hacer al c�digo. Tomcat no borra autom�ticamente el directorio desempaquetado o el archivo WAR cuando lo apagas. Adem�s, Tomcat no detecta los cambios en el archivo WAR, por eso no despliega autom�ticamente nuevas versiones de una aplicaci�n cuando se copian nuevos ficheros WAR sobre los viejos en el directorio de despliegue de Tomcat (excepto en el caso de espec�ficarlo est�ticamente en el fichero de configuraci�n server.xml de Tomcat). Por estas razones es importante tener un target undeploy en el fichero build.xml. A�ade el siguiente fragmento de XML despu�s del target deploy:
<target name="undeploy" depends="init" description="Undeploy the application from Tomcat"> <delete dir="${deploy.dir}/${war.base.name}"/> <delete file="${deploy.dir}/${war.base.name}.war"/> </target>
Como ahora tienes targets que funcionan en tu fichero de construcci�n Ant, deber�as cambiar el target por defecto. Actualmente tienes esto en tu fichero build.xml:
<project name="Phone List Application" basedir=".">
Deber�as cambiarlo por lo siguiente:
<project name="Phone List Application" default="package-war" basedir=".">
En este punto, tienes un fichero de construcci�n con la habilidad de compilar y desplegar la aplicaci�n con una s�la l�nea de comando. La construcci�n autom�tica ser� esencial durante el proceso de desarrollo. Mira el fichero build.xml incluido en el c�digo de ejemplo. El fichero build.xml se llama build.xml.v1. Esencialmente es el mismo que acabas de crear, pero tiene las cosas en un orden diferente que lo hacen m�s f�cil de leer y de mantener.
Podr�as elegir utilizar el fichero build.xml.v1 como tu base para avanzar, pero no tienes porque hacerlo. Le a�adir�s m�s c�digo XML para a�adir tests. Si eliges utilizarlo, asegurate de renombarlo como build.xml despu�s de copiarlo al directorio ~/projects/phonelist.