My favorites | Português | Sign in

Como usar o Apache Ant

Se você não estiver usando o Eclipse e o o Plug-in do Google para o Eclipse, provavelmente precisará de outra forma de gerenciar o processo de construção e teste do seu aplicativo do Google App Engine. O Apache Ant facilita o gerenciamento do seu projeto a partir da linha de comando ou de outros IDEs que funcionam com o Ant. O SDK para Java inclui um conjunto de macros do Ant para execução de tarefas comuns de desenvolvimento do Google App Engine, incluindo a inicialização do servidor de desenvolvimento e o envio do aplicativo para o Google App Engine.

Este artigo descreve um arquivo de construção do Ant útil para a maioria dos projetos. Para ignorar a descrição e ir direto ao arquivo completo para copiar e colar, consulte O arquivo de construção completo.

Instalação do Ant

Caso você ainda não tenha o Ant instalado no seu sistema, visite o site do Apache Ant para fazer o download e instalá-lo.

Quando o Ant estiver instalado e o comando ant estiver no caminho do comando, você poderá executar o seguinte comando para verificar se ele funciona e ver qual versão está instalada:

ant -version

O diretório do projeto

Conforme descrito no Guia Primeiros passos, seu projeto do Google App Engine deve produzir uma estrutura de diretórios usando o layout padrão WAR para aplicativos da web em Java (arquivos WAR ainda não são suportados pelo SDK).

Para obter essas instruções, colocaremos todos os arquivos relacionados ao projeto em um único diretório chamado Guestbook/ (para o projeto de livro de visitas descrito no Guia Primeiros passos), com um subdiretório chamado src/ para o código fonte Java e um subdiretório chamado war/ para os arquivos do aplicativo concluídos. O processo de construção compila o código fonte e coloca o bytecode Java compilado no local adequado em war/. Você criará outros arquivos para o WAR diretamente no diretório war/.

O diretório completo do projeto deve ter a seguinte aparência:

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 criar essa estrutura de diretórios a partir do prompt de comando, use os comandos abaixo. Se você estiver usando o Windows, mude as barras / nesses caminhos para barras invertidas \ (no próprio arquivo Ant, os caminhos que usam barras / funcionam em todos os sistemas operacionais).

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

Criação do arquivo de construção

No diretório Guestbook/, crie um arquivo chamado build.xml com o seguinte conteúdo:

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

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

</project>

Este arquivo de construção ainda não faz nada: ele não contém um "destino" com instruções para execução de tarefas. O arquivo define duas propriedades do Ant, que usaremos ao definirmos os destinos e os caminhos posteriormente.

A propriedade sdk.dir é o caminho para o SDK para Java do Google App Engine, o diretório appengine-java-sdk criado ao descompactar o arquivo compactado do SDK. O "../appengine-java-sdk" assume que este diretório está no diretório pai acima do diretório do projeto. Ajuste esse valor, se for necessário (os caminhos são relativos ao local do arquivo build.xml).

O elemento <import> carrega um conjunto de macros do Ant para o desenvolvimento do Google App Engine, incluído no SDK para Java do Google App Engine. Usaremos diversas macros desse tipo mais tarde.

Definição do caminho da classe

Ao compilar as suas classes, o caminho da classe Java deve conter os JARs da API do Google App Engine e quaisquer outros JARs que você pode ter adicionado ao diretório war/WEB-INF/lib/ do seu projeto (como os JARs JDO/JPA do DataNucleus). O aplicativo pode acessar classes a partir dos JARs adicionados a esse diretório. Além disso, os JARs no diretório lib/shared/ do SDK estarão no caminho da classe.

Edite o build.xml e adicione as seguintes linhas acima da tag </project> de fechamento para definir um caminho de classe que contenha esses JARs:

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

Como copiar JARs

O seu aplicativo deve incluir appengine-api-*.jar (em que * representa um número de versão da API e do SDK), um JAR incluído com o SDK, no diretório war/WEB-INF/lib/. O Google App Engine procura classes desse JAR para determinar qual versão da API o seu aplicativo está usando. Se o seu aplicativo usa as interfaces JDO ou JPA no armazenamento de dados do Google App Engine, o aplicativo deverá incluir a implementação JDO/JPA no war/WEB-INF/lib/. Todos esses JARs estão no diretório lib/user/ do SDK.

Você pode copiar esses JARs no WAR manualmente. No entanto, é útil fazer da cópia desses JARs uma parte do processo de construção. Isso garante que o seu aplicativo usa as mesmas versões dessas interfaces que as incluídas no SDK, mesmo se você atualizar o SDK posteriormente.

Todos os JARs devem estar no diretório war/WEB-INF/lib/. Eles não podem ficar em subdiretórios. Esse destino do Ant copiará os JARs recursivamente do ${sdk.dir}/lib/user/ usando o atributo flatten="true" da tarefa copyde modo que todos os JARs fiquem no mesmo diretório.

Edite o build.xml e adicione as seguintes linhas acima da tag </project> de fechamento:

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

Isso cria um destino de compilação chamado "copyjars"que copia os JARs no local apropriado. Para testar esse destino, verifique se o diretório de trabalho atual é o diretório do projeto (Guestbook/) e execute o seguinte comando:

ant copyjars

Verifique o conteúdo de war/WEB-INF/lib/ para ter certeza de que os JARs estão lá.

Compilação dos arquivos de origem

Edite o build.xml e adicione as seguintes linhas acima da tag </project> de fechamento:

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

Isso define um destino de compilação chamado "compile" que compila todos os arquivos de origem Java encontrados no diretório src/ e armazena as classes compiladas no war/WEB-INF/classes/. Todos os outros arquivos encontrados no src/, como o diretório META-INF/, são copiados literalmente para war/WEB-INF/classes/. O destino depende do "copyjars", por isso os dois destinos são compilados, se necessário.

Para compilar os arquivos de origem do seu projeto, execute o seguinte comando:

ant compile

Aprimoramento das classes JDO

Esta seção descreve como usar o Ant para construir o seu projeto com suporte para a interface JDO (Objetos da dados Java) no armazenamento de dados. Se o seu projeto não usa a interface JDO, continue na próxima seção.

Conforme descrito no Guia Primeiros passos e na documentação do armazenamento de dados, a interface JDO permite o armazenamento de instâncias das suas classes no armazenamento de dados e a recuperação delas posteriormente como objetos. Você descreve como as instâncias devem ser armazenadas e recuperadas usando as anotações Java na definição da classe.

Para a JDO ver as anotações, você precisa processar o bytecode das suas classes de dados após compilá-las usando uma ferramenta incluída no DataNucleus Access Platform, a implementação JDO distribuída com o Google App Engine. O DataNucleus descreve esse processo como "aprimoramento" das classes.

O SDK do Google App Engine inclui macros do Ant para aprimoramento das classes de dados JDO. A macro <enhance_war> aprimora cada classe de dados JDO no projeto, usando o caminho de classe correto para o projeto. Para obter um controle mais preciso, você pode usar a macro <enhance>.

Edite o build.xml e adicione as seguintes linhas acima da tag </project> de fechamento:

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

Esse destino depende do "compile", por isso a compilação desse destino garante que as classes foram compiladas e estão atualizadas antes da execução da tarefa de aprimoramento.

Execução do servidor de desenvolvimento

Você pode executar o servidor da web para desenvolvimento usando uma macro do Ant. Ao fazer esse destino depender do destino "datanucleusenhance" (ou do destino "compile" se não estiver usando o DataNucleus), você pode construir o seu projeto e iniciar o servidor com apenas um comando simples.

Edite o build.xml e adicione as seguintes linhas acima da tag </project> de fechamento:

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

Você pode fornecer ao servidor de desenvolvimento argumentos usando os atributos e um elemento <options>. Por exemplo, o seguinte destino inicia o servidor usando a porta 8888 e ativa a depuração remota de Java na porta 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 construir o projeto e executar o servidor, use o seguinte comando:

ant runserver

Para interromper o servidor, pressione Control-C.

Envio e outras tarefas do AppCfg

Você pode definir as tarefas do Ant para enviar o aplicativo ao Google App Engine e executar outras ações fornecidas pelo AppCfg.

A macro <appcfg> assume o nome da ação como o atributo action e o caminho para o WAR do projeto como o atributo war. O elemento pode ter elementos <options> e <args> opcionais.

Edite o build.xml e adicione as seguintes linhas:

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

O arquivo de construção completo

Veja aqui o arquivo build.xml completo descrito por essas instruções:

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