Избранное | Русский | Войти

Использование Apache Ant

Если вы не используете Eclipse и плагин Google для Eclipse, вам может потребоваться другой способ управления процессом создания и тестирования приложения App Engine. Apache Ant упрощает управление проектом из командной строки или других сред IDE, работающих с Ant. SDK Java содержит набор макросов Ant для выполнения распространенных задач разработки App Engine, включая запуск сервера разработки и добавление приложения на App Engine.

В данной статье описывается файл сборки Ant, полезный для множества проектов. Чтобы пропустить описание и перейти непосредственно к полному файлу для копирования и вставки, перейдите к разделу Полный файл сборки.

Установка Ant

Если Ant еще не установлен на вашем компьютере, посетите веб-сайт Apache Ant, чтобы загрузить и установить его.

После установки Ant и добавления команды ant в путь можно выполнить следующую команду для проверки правильности работы и просмотра установленной версии:

ant -version

Каталог проекта

Как описано в Руководстве по началу работы, проект App Engine должен создавать структуру каталогов, используя стандартный шаблон WAR для веб-приложений Java. (Архивные файлы WAR пока не поддерживаются SDK.)

Для этих инструкций мы поместим все относящиеся к проекту файлы в один каталог под названием Guestbook/ (для проекта гостевой книги, описанного в Руководстве по началу работы) с подкаталогом src/ для исходного кода Java и подкаталогом war/ для готовых файлов приложения. В процессе сборки будет скомпилирован исходный код, а скомпилированный байтовый код Java будет помещен в соответствующее место в подкаталоге war/. Остальные файлы для каталога WAR будут созданы непосредственно в каталоге war/.

Полный каталог проекта должен выглядеть примерно так:

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

Для создания этой структуры каталогов из командой строки используйте следующие команды. При работе в Windows замените прямые косые черты / в этих путях на обратные косые черты \. (В самом файле Ant пути с прямыми косыми чертами / работают для всех операционных систем.)

mkdir Guestbook
cd Guestbook
mkdir -p src/META-INF
mkdir -p war/WEB-INF/classes
mkdir -p war/WEB-INF/lib

Создание файла сборки

В каталоге Guestbook/ создайте файл build.xml следующего содержания:

<project>
  <property name="sdk.dir" location="../appengine-java-sdk" />

  <import file="${sdk.dir}/config/user/ant-macros.xml" />

</project>

Данный файл сборки пока ничего не выполняет: в нем отсутствует тег "target" с инструкциями для выполнения задач. В файле определяется два свойства Ant, которые будут использоваться для определения тегов "target" и в дальнейшем.

Свойство sdk.dir – это путь к SDK Java App Engine; каталог appengine-java-sdk был создан при распаковке Zip-файла SDK. "../appengine-java-sdk" подразумевает, что этот каталог находится в родительском каталоге в каталоге проекта. При необходимости измените это значение. (Пути являются относительными к расположению файла build.xml.)

Элемент <import> загружает набор макросов для разработки App Engine, включенный в SDK Java App Engine. Несколько из них будут использованы позже.

Определение пути класса

При компиляции классов путь к классу Java должен содержать файлы JAR для API App Engine и все остальные файлы JAR, которые вы добавляли в каталог war/WEB-INF/lib/ проекта (например, файлы JAR DataNucleus JDO/JPA). Приложение может обращаться к классам из файлов JAR, добавленных в этот каталог. Кроме того, файлы JAR в каталоге lib/shared/ SDK будут находиться по пути к классу.

Измените файл build.xml и добавьте в него следующие строки над закрывающим тегом </project> для определения пути к классу, содержащему эти файлы 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>

Копирование файлов JAR

Приложение должно включать файл appengine-api-*.jar (где * – это номер версии API и SDK), файл JAR, включенный в SDK, в каталоге war/WEB-INF/lib/. App Engine проверяет классы в этом файле JAR для определения версии API, используемого приложением. Если приложение использует интерфейсы JDO или JPA для хранилища данных App Engine, приложение должно включать реализацию JDO/JPA в war/WEB-INF/lib/. Все эти файлы JAR находятся в каталоге lib/user/ SDK.

Можно скопировать эти файлы JAR в WAR вручную. Однако полезно сделать копирование этих файлов JAR частью процесса сборки. Это обеспечивает использование приложением тех же версий интерфейсов, которые включены в SDK, даже при обновлении SDK в дальнейшем.

Все файлы JAR должны находиться в каталоге war/WEB-INF/lib/, они не могут находиться в подкаталогах. Этот тег Ant "target " рекурсивно скопирует файлы JAR из подкаталога ${sdk.dir}/lib/user/, используя атрибут flatten="true" задачи copy, чтобы все файлы JAR оказались в одном каталоге.

Измените файл build.xml и добавьте в него следующие строки над закрывающим тегом </project>:

  <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" сборки под названием "copyjars", копирующий файлы JAR в соответствующее местоположение. Для проверки этого тега "target" убедитесь, что текущим рабочим каталогом является каталог проекта (Guestbook/), затем выполните следующую команду:

ant copyjars

Проверьте содержимое подкаталога war/WEB-INF/lib/, чтобы убедиться в наличии файлов JAR.

Компиляция исходных файлов

Измените файл build.xml и добавьте следующие строки над закрывающим тегом </project>:

  <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" сборки "compile", компилирующий все исходные файлы Java, которые размещаются в каталоге src/, и сохраняющий скомпилированные классы в подкаталоге war/WEB-INF/classes/. Все остальные файлы, находящиеся в подкаталоге src/, например в каталоге META-INF/, копируются в каталог war/WEB-INF/classes/. Тег "target" зависит от "copyjars", поэтому при необходимости создаются оба тега "target".

Для компиляции исходных файлов проекта выполните следующую команду:

ant compile

Расширение классов JDO

В данном разделе описывается использование Ant для создания проекта с поддержкой интерфейса JDO (объекты данных Java) для хранилища данных. Если в проекте не используется интерфейс JDO, можно перейти к следующему разделу.

Как описано в Руководстве по началу работы и документации хранилища данных, интерфейс JDO позволяет сохранять экземпляры классов в хранилище данных и в дальнейшем получать их как объекты. Способ сохранения и получения экземпляров описывается с помощью аннотаций Java в определении класса.

Чтобы интерфейс JDO видел аннотации, необходимо обработать байтовый код для классов данных после их компиляции с помощью инструмента, включенного в платформу DataNucleus Access Platform, реализацию JDO, распространяемую с App Engine. DataNucleus описывает этот процесс как "расширение" классов.

SDK App Engine содержит макросы Ant для расширения классов данных JDO. Макрос <enhance_war> расширяет все классы данных JDO в проекте, используя верный путь класса для проекта. Для более точного контроля можно использовать макрос <enhance>.

Измените файл build.xml и добавьте следующие строки над закрывающим тегом </project>:

  <target name="datanucleusenhance" depends="compile"
      description="Performs JDO enhancement on compiled data classes.">
    <enhance_war war="war" />
  </target>

Этот тег "target" зависит от "compile", поэтому его создание обеспечивает компиляцию и актуальность классов до выполнения расширения.

Работа с веб-сервером разработки

Веб-сервер разработки можно запустить с помощью макроса Ant. Путем установки зависимости данного тега "target" от тега "target" "datanucleusenhance" (или тега "target" "compile", если DataNucleus не используется) можно создать проект и запустить сервер с помощью одной простой команды.

Измените файл build.xml и добавьте следующие строки над закрывающим тегом </project>:

  <target name="runserver" depends="datanucleusenhance"
      description="Starts the development server.">
    <dev_appserver war="war" />
  </target>

Можно предоставить серверу разработки аргументы с помощью атрибутов и элемента <options>. Например, следующий тег "target" запускает сервер, используя порт 8888, и включает удаленную отладку Java через порт 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>

Для создания проекта и запуска сервера используйте следующую команду:

ant runserver

Для остановки сервера нажмите Control-C.

Добавление и другие задачи AppCfg

Можно определить задачи Ant для добавления приложения в App Engine и выполнения других действий, предоставленных командной AppCfg.

Макрос <appcfg> принимает название действия в качестве атрибута action и путь к WAR проекта в качестве атрибута war. Элемент может иметь дополнительные элементы <options> и <args>.

Измените файл build.xml и добавьте в него следующие строки:

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

Полный файл сборки

Ниже приведен полный файл build.xml, описанный в этих инструкциях:

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