Mis favoritos | Español | Acceder

Uso de Apache Ant

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.

Instalación de Ant

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

Directorio del proyecto

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

Generación del archivo de creación

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.

Definición de la ruta de clase

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>

Copia de los JAR

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í.

Compilación de archivos fuente

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

Mejora de las clases JDO

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.

Ejecución del servidor de desarrollo

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.

Subida y otras tareas de AppCfg

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>

El archivo de creación completo

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>