Google Code disponible en: English - Español - 日本語 - 한국어 - Português - Pусский - 中文(简体) - 中文(繁體)
Si no utilizas ni Eclipse ni el complemento de Google para Eclipse, probablemente prefieras otra forma de administrar el proceso de compilación y de prueba de tu aplicación App Engine. Apache Ant facilita la administración de tu proyecto desde la línea de comandos o desde otros entornos de desarrollo integrados (IDE) compatibles con Ant. El SDK de Java incluye un conjunto de macros de Ant para realizar tareas de desarrollo de App Engine, entre las que se incluyen el inicio del servidor de desarrollo y la subida de la aplicación a App Engine.
Este archivo describe un archivo de creación de Ant que sirve para la mayoría de proyectos. Para omitir la descripción y consultar directamente el archivo completo para copiarlo y pegarlo, consulta El archivo de creación completo.
Si aún no has instalado Ant en tu sistema, visita el sitio web de Apache Ant para descargarlo e instalarlo.
Cuando Ant esté instalado y el comando ant se encuentre en la ruta de comandos, puedes ejecutar el siguiente comando para comprobar que funciona y para ver qué versión está instalada:
ant -version
Como se describe en la Guía de introducción, el proyecto de App Engine debe generar una estructura de directorio que utilice el formato estándar WAR para aplicaciones web Java. (Los archivos del archivo WAR no son compatibles con el SDK).
Para estas instrucciones, ubicaremos todos los archivos relacionados con el proyecto en un único directorio denominado Guestbook/ (para el proyecto del libro de invitados descrito en la Guía de introducción), junto con un subdirectorio denominado src/ para el código fuente Java y otro denominado war/ para los archivos de la versión definitiva de tu aplicación. El proceso de compilación compila el código fuente y coloca el código de bytes de Java compilado en la ubicación adecuada en war/. Puedes crear otros archivos para el WAR directamente en el directorio war/.
El directorio completo del proyecto debería parecerse a:
Guestbook/
src/
...Java source code...
META-INF/
...other configuration...
war/
...JSPs, images, data files...
WEB-INF/
...app configuration...
classes/
...compiled classes...
lib/
...JARs for libraries...
Para crear esta estructura de directorio desde la línea de comandos, utiliza los siguientes comandos. Si utilizas Windows, cambia las barras inclinadas / de estas rutas por barras inversas \. (Dentro del propio archivo de Ant, las rutas con barras inclinadas / funcionan en todos los sistemas operativos).
mkdir Guestbook cd Guestbook mkdir -p src/META-INF mkdir -p war/WEB-INF/classes mkdir -p war/WEB-INF/lib
En el directorio Guestbook/, crea un archivo llamado build.xml con el siguiente contenido:
<project>
<property name="sdk.dir" location="../appengine-java-sdk" />
<import file="${sdk.dir}/config/user/ant-macros.xml" />
</project>
Este archivo de creación aún no tiene ninguna función: no contiene ningún "destino" con instrucciones para realizar tareas. El archivo define dos propiedades de Ant, que utilizaremos cuando definamos destinos y rutas más adelante.
La propiedad sdk.dir es la ruta al SDK de Java de App Engine, el directorio appengine-java-sdk creado al descomprimir el archivo Zip del SDK. "../appengine-java-sdk" asume que este directorio está en el directorio principal por encima del directorio de proyecto. Ajusta este valor en caso necesario. (Las rutas están relacionadas con la ubicación del archivo build.xml).
El elemento <import> carga un conjunto de macros de Ant para el desarrollo de App Engine incluido en el SDK de Java de App Engine. Utilizaremos algunas de estas macros más adelante.
Si compilas tus clases, la ruta de clase Java debe contener los JAR para el API de App Engine, así como otros JAR que puedes haber añadido al directorio war/WEB-INF/lib/ del proyecto (como, por ejemplo, los JAR de JDO/JPA de DataNucleus). La aplicación puede acceder a las clases desde los JAR añadidos a este directorio. Además, los JAR del directorio lib/shared/ del SDK están en la ruta de clase.
Edita build.xml y añade las siguientes líneas sobre la etiqueta </project> de cierre para definir la ruta de clase que contiene estos JAR:
<path id="project.classpath">
<pathelement path="war/WEB-INF/classes" />
<fileset dir="war/WEB-INF/lib">
<include name="**/*.jar" />
</fileset>
<fileset dir="${sdk.dir}/lib">
<include name="shared/**/*.jar" />
</fileset>
</path>
Tu aplicación debe incluir appengine-api-*.jar (donde * representa un número de versión del API y del SDK), un JAR incluido en el SDK en el directorio war/WEB-INF/lib/. App Engine comprueba las clases de este JAR para determinar la versión del API que utiliza tu aplicación. Si la aplicación utiliza las interfaces JDO o JPA en el almacén de datos de App Engine, esta debe incluir la implementación de JDO/JPA en war/WEB-INF/lib/. Todos estos JAR están en el directorio lib/user/ del SDK.
Puedes copiar estos JAR en el WAR de forma manual. Sin embargo, es útil copiar estos JAR durante el proceso de compilación, ya que esto asegura que tu aplicación utilice las mismas versiones de estas interfaces que las incluidas en el SDK, aunque actualices el SDK en otro momento.
Todos los JAR deben estar en el directorio war/WEB-INF/lib/, no en subdirectorios. Este destino de Ant copia repetidamente desde ${sdk.dir}/lib/user/ a través del atributo flatten="true" de la tarea copy para que todos los JAR terminen en el mismo directorio.
Edita build.xml y añade las siguientes líneas debajo de la etiqueta </project> de cierre:
<target name="copyjars"
description="Copies the App Engine JARs to the WAR.">
<copy
todir="war/WEB-INF/lib"
flatten="true">
<fileset dir="${sdk.dir}/lib/user">
<include name="**/*.jar" />
</fileset>
</copy>
</target>
Esto genera un destino de creación denominado "copyjars" que copia los JAR en la ubicación adecuada. Para probar este destino, asegúrate de que el directorio de trabajo actual sea el directorio de proyecto (Guestbook/) y, a continuación, ejecuta el siguiente comando:
ant copyjars
Comprueba el contenido de war/WEB-INF/lib/ para asegurarte de que los JAR se encuentren allí.
Edita build.xml y añade las siguientes líneas debajo de la etiqueta </project> de cierre:
<target name="compile" depends="copyjars"
description="Compiles Java source and copies other source files to the WAR.">
<mkdir dir="war/WEB-INF/classes" />
<copy todir="war/WEB-INF/classes">
<fileset dir="src">
<exclude name="**/*.java" />
</fileset>
</copy>
<javac
srcdir="src"
destdir="war/WEB-INF/classes"
classpathref="project.classpath"
debug="on" />
</target>
Esto define un destino de creación denominado "compile" que compila todos los archivos de origen Java en el directorio src/ y almacena las clases compiladas en war/WEB-INF/classes/. Todos los demás archivos ubicados en src/ como, por ejemplo, el directorio META-INF/, se copian textualmente en war/WEB-INF/classes/. El destino depende de "copyjars", por lo que, en caso necesario, se crean ambos destinos.
Para compilar los archivos fuente de tu proyecto, ejecuta el siguiente comando:
ant compile
Esta sección describe cómo utilizar Ant para que tu proyecto admita la interfaz de objetos de datos Java (JDO) en el almacén de datos. Si tu proyecto no utiliza la interfaz JDO, puedes pasar a la siguiente sección.
Como se describe en la Guía de introducción y en la documentación del almacén de datos, la interfaz JDO permite almacenar instancias de tus clases en el almacén de datos y recuperarlas en otro momento como objetos. Describe cómo se almacenan y se recuperan las instancias a través de anotaciones Java en la definición de clase.
Para que JDO vea las anotaciones, debes procesar el código de bytes de tus clases de datos después de compilarlas mediante una herramienta incluida en DataNucleus Access Platform, la implementación de JDO distribuida junto con App Engine. DataNucleus describe este proceso como un "mejora" de las clases.
El SDK de App Engine incluye macros de Ant para mejorar las clases de datos JDO. La macro <enhance_war> mejora todas las clases de datos JDO del proyecto a través de la ruta de clase correcta del proyecto. Para un control más preciso, puedes utilizar la macro <enhance>.
Edita build.xml y añade las siguientes líneas debajo de la etiqueta </project> de cierre:
<target name="datanucleusenhance" depends="compile"
description="Performs JDO enhancement on compiled data classes.">
<enhance_war war="war" />
</target>
Este destino depende de "compile", por lo que su creación asegura que las clases se hayan compilado y que estén actualizadas antes de realizar la tarea de mejora.
Puedes ejecutar el servidor web de desarrollo a través de la macro de Ant. Al hacer que este destino dependa del destino "datanucleusenhance" (o del destino "compile" si no utilizas DataNucleus), puedes crear tu proyecto e iniciar el servidor a través de un sencillo comando.
Edita build.xml y añade las siguientes líneas debajo de la etiqueta </project> de cierre:
<target name="runserver" depends="datanucleusenhance"
description="Starts the development server.">
<dev_appserver war="war" />
</target>
Puedes asignar argumentos al servidor de desarrollo a través de atributos y de un elemento <options>. Por ejemplo, el siguiente destino inicia el servidor a través del puerto 8888 y permite la depuración de Java remota en el puerto 9999:
<target name="runserver" depends="datanucleusenhance"
description="Starts the development server.">
<dev_appserver war="war" port="8888" >
<options>
<arg value="--jvm_flag=-Xdebug"/>
<arg value="--jvm_flag=-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=9999"/>
</options>
</dev_appserver>
</target>
Para crear el proyecto y ejecutar el servidor, utiliza el siguiente comando:
ant runserver
Para detener el servidor, pulsa las teclas Control-C.
Puedes definir tareas de Ant para subir la aplicación a App Engine y realizar otras acciones que ofrece AppCfg.
La macro <appcfg> adopta el nombre de la acción como el atributo action y la ruta al WAR del proyecto como el atributo war. El elemento puede contener <options> opcionales y elementos <args>.
Edita build.xml y añade las siguientes líneas:
<target name="update" depends="datanucleusenhance"
description="Uploads the application to App Engine.">
<appcfg action="update" war="war" />
</target>
<target name="update_indexes" depends="datanucleusenhance"
description="Uploads just the datastore index configuration to App Engine.">
<appcfg action="update_indexes" war="war" />
</target>
<target name="rollback" depends="datanucleusenhance"
description="Rolls back an interrupted application update.">
<appcfg action="rollback" war="war" />
</target>
<target name="request_logs"
description="Downloads log data from App Engine for the application.">
<appcfg action="request_logs" war="war">
<options>
<arg value="--num_days=5"/>
</options>
<args>
<arg value="logs.txt"/>
</args>
</appcfg>
</target>
Las instrucciones que se muestran a continuación describen el archivo build.xml completo:
<project>
<property name="sdk.dir" location="../appengine-java-sdk" />
<import file="${sdk.dir}/config/user/ant-macros.xml" />
<path id="project.classpath">
<pathelement path="war/WEB-INF/classes" />
<fileset dir="war/WEB-INF/lib">
<include name="**/*.jar" />
</fileset>
<fileset dir="${sdk.dir}/lib">
<include name="shared/**/*.jar" />
</fileset>
</path>
<target name="copyjars"
description="Copies the App Engine JARs to the WAR.">
<copy
todir="war/WEB-INF/lib"
flatten="true">
<fileset dir="${sdk.dir}/lib/user">
<include name="**/*.jar" />
</fileset>
</copy>
</target>
<target name="compile" depends="copyjars"
description="Compiles Java source and copies other source files to the WAR.">
<mkdir dir="war/WEB-INF/classes" />
<copy todir="war/WEB-INF/classes">
<fileset dir="src">
<exclude name="**/*.java" />
</fileset>
</copy>
<javac
srcdir="src"
destdir="war/WEB-INF/classes"
classpathref="project.classpath"
debug="on" />
</target>
<target name="datanucleusenhance" depends="compile"
description="Performs JDO enhancement on compiled data classes.">
<enhance_war war="war" />
</target>
<target name="runserver" depends="datanucleusenhance"
description="Starts the development server.">
<dev_appserver war="war" />
</target>
<target name="update" depends="datanucleusenhance"
description="Uploads the application to App Engine.">
<appcfg action="update" war="war" />
</target>
<target name="update_indexes" depends="datanucleusenhance"
description="Uploads just the datastore index configuration to App Engine.">
<appcfg action="update_indexes" war="war" />
</target>
<target name="rollback" depends="datanucleusenhance"
description="Rolls back an interrupted application update.">
<appcfg action="rollback" war="war" />
</target>
<target name="request_logs"
description="Downloads log data from App Engine for the application.">
<appcfg action="request_logs" war="war">
<options>
<arg value="--num_days=5"/>
</options>
<args>
<arg value="logs.txt"/>
</args>
</appcfg>
</target>
</project>