Tag: ant

Problemas de compatibilidade de versões no Java: especificando a versão do JDK para compilação

Uma das preocupações ao compilarmos aplicações e bibliotecas em Java é que a versão usada para compilação seja compatível com a versão onde o código será executado.

Por exemplo, você pode ter o Java 7 instalado em seu computador de desenvolvimento. Se você gerar um jar e tentar executar no computador de um cliente com o Java 6 pode ocorrer um erro!

Compilação em modo de compatibilidade

A primeira solução para problemas com versões diferentes é configurar o compilador para compilar em modo de compatibilidade.

Mas há um problema: isso não garante que o código executá. A cada versão do Java, classes ganham novos métodos e novas classes são adicionadas. A compilação em modo compatibilidade irá suceder sem erros, mas ao executar as classes em versões anteriores do Java, ocorrerão erros de tempo de execução por falta dos métodos e classes que não existem nas APIs nativas naquela versão.

Um exemplo simples é o construtor da classe BigDecimal que recebe um inteiro. Ele foi adicionado no Java 5, mas um código que use esse construtor é compilado sem problemas em compatibilidade para Java 1.4. Obviamente, ao executar esse código num JRE 1.4 ocorrerá um erro fatal.

Especificando um JDK alternativo

Então temos a segunda solução, que nos traz garantia de funcionamento: compilar o código com a mesma versão do ambiente do cliente.

Isso não significa, entretanto, que precisamos excluir todas as demais versões do Java de nosso ambiente de desenvolvimento, muito menos que só poderemos trabalhar com uma única versão em todos os projetos.

É possível especificar uma versão alternativa do Java para cada projeto, seja no Eclipse, Ant ou Maven.

Para ver como instalar o JDK 7, consulte o artigo Instalando e Configurando o Java Development Kit 7 para Desenvolvimento.

Especificando a versão e o JDK no Maven

No pom.xml podemos configurar o maven-compiler-plugin da seguinte forma:

  • <source>: especifica a versão do Java em que está escrito o código-fonte.
  • <target>: especifica para qual versão do Java o compilador deve compilar o código.
  • <executable>: especifica qual compilador (javac) será usado.

Exemplo:

<!-- CONFIGURAR VERSÃO DO JAVA PARA 1.7 -->
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
                <source>1.7</source>
                <target>1.7</target>
                <executable>C:\Program Files\Java\jdk1.7.0_45\bin\javac</executable>
            </configuration>
        </plugin>
    </plugins>
</build>

Veja a documentação aqui.

Configuração única para um grupo de projetos usando herança

Não é necessário ter a configuração acima em cada novo projeto. Você pode criar um parent pom e usar a herança para reaproveitar essa configuração em todos os seus projetos.

Veja como especificar o pai de um projeto:

<parent>
    <groupId>org.minhaempresa</groupId>
    <artifactId>meu-pom-principal</artifactId>
    <version>1.0.0</version>
</parent>

Configuração única para todos os ambientes

Um problema que pode ocorrer é que cada desenvolvedor tem uma instalação do Java em local diferente. Se houver um servidor de integração contínua, o problema é o mesmo. Como especificar o Java sem ter que ajustar o caminho em cada máquina?

Para resolver isso, podemos criar um perfil (profile) diretamente na configuração do Maven. Um perfil nada mais é que um conjunto de configurações que você pode ativar e desativar quando quiser. Se essa configuração for feita em cada instalação do Maven e o perfil for ativado por padrão, podemos especificar a versão do Java em cada local sem maiores dificuldades.

Primeiro, edite o seu arquivo settings.xml que fica na sua pasta de usuário ou então no diretório conf da instalação do Maven e adicione um perfil com uma propriedade especificando onde está o Java.

Exemplo:

<profiles>
    <profile>
        <id>compiler</id>
        <properties>
            <JDK7>C:\Program Files\Java\jdk1.7.0_45</JDK7>
            <JDK4>C:\Program Files\Java\jdk1.4</JDK4>
        </properties>
    </profile>
</profiles>

No código acima, definimos duas propriedades JDK7 e JDK4. Note que você pode definir quantas propriedades quiser.

Agora devemos ativar o perfil para todos os projetos que usem essa instalação do Maven, editando novamente o settings.xml e adicionando o seguinte trecho:

<activeProfiles>
    <activeProfile>compiler</activeProfile>
</activeProfiles>

Então, em seu projeto ou parent pom, use a propriedade definida assim:

<executable>${JDK7}/bin/javac</executable>

Definindo o JDK num projeto do Eclipse

Ao abrir o Eclipse, ele virá configurado com mesmo o JDK usado para executá-lo, ou seja, o que estiver configurado como padrão em seu computador. Todavia, você pode incluir na configuração do Eclipse quantas versões quiser, tanto do JDK (compilação) quanto do JRE (execução).

Incluindo uma instalação do Java no Eclipse

Primeiro, acesse o menu Window > Preferences... e vá até a configuração Java > Installed JREs.

01

Clique em Add....

02

Selecione a opção Standard VM e clique em Next >.

03

Preencha o campo JRE home digitando o diretório de instalação do Java que você quer adicionar. Ou clique em Directory... para procurar a pasta. O Eclipse irá preencher as demais informações para você.

04

Clique em Finish e a nova instalação será adicionada à lista.

05

Clique em OK.

Configurando o projeto para usar uma versão específica do Java

Clique com o botão direito em um projeto e acesse a opção Properties. Clique no item Java Build Path e vá até a aba Libraries.

06

Selecione o Java atualmente em uso e clique no botão Edit....

07

Selecione o item Alternate JRE, selecione a JRE ou JDK que você quer usar e clique em Finish.

08

Verifique se o Java mudou e clique em OK para concluir a configuração.

Talvez o Eclipse emita um aviso de que será necessário recompilar o projeto. Isso é normal, apenas confirme.

Note que para projetos que usam o plugin do Maven para o Eclipse (M2E), você não precisa fazer isso manualmente. Apenas adicione o JDK ao Eclipse, como descrito acima, e configure seu pom.xml. O plugin selecionará o Java mais adequado para o projeto automaticamente.

Especificando o JDK num build Ant

Caso você faça a compilação e empacotamento de seus projetos com scripts Ant, é possível especificar a versão de compilação para a task <javac> de uma forma muito simples. Basta definir o atributo executable, por exemplo:

<javac srcdir="" 
    destdir=""
    executable="path-to-java14-home/bin/javac" 
    fork="true"
    taskname="javac1.4" />

Considerações finais

Especificar uma versão do Java é uma boa prática para evitar problemas inesperados durante a entrega de um software. Procure compilar e testar seus programas usando a mesma versão do ambiente onde eles serão executados.

Este artigo descreve várias formas de atingir isso, para você ter um ambiente de desenvolvimento “saudável”.

Por este e outros motivos, recomendo o uso do Maven para novos projetos, já que ele evita a repetição do processo de configuração do ambiente para cada novo desenvolvedor ou servidor.

Para maiores detalhes sobre o Maven, consulte o artigo: Instalando, configurando e usando o Maven para gerenciar suas dependências e seus projetos Java.

Uma introdução ao Ant

554px-Apache-Ant-logo.svg

Ambientes de desenvolvimento Java, tanto em Linux quanto em Windows, precisam de algum tipo de automação para diminuir o tempo despendido pelo desenvolvedor, por exemplo, para gerar uma release (versão do sistema para distribuição ou homologação).

Uma das formas de automatizar tarefas uniformemente em todos os ambientes é usar uma ferramenta como o Apache Ant.

Ant é uma ferramenta poderosa e versátil que permite a criação de builds para compilação de código, montagem de pacotes, tratamento e conversão de arquivos e muito mais.

Não estamos falando de uma linguagem de programação. Ant é uma forma de declaração de atividades (tasks) necessárias em um determinado processo. Isso é feito através de um ou mais arquivos XML.

Instalando o Ant

Baixe o pacote binário na página de download oficial, descompacte-o numa pasta e adicione o caminho ao PATH do seu sistema operacional.

No Windows podemos fazer isso para uma sessão do prompt de comando da seguinte forma:

set path=%path%;c:\caminho\apache-ant-1.9.3\bin

Esta técnica é adequada se for necessário usar mais de uma versão do Ant. Mas o melhor é alterar o PATH diretamente nas configurações de sistema para sempre tê-lo disponível em linha de comando.

Escrevendo um build no Ant

O seguinte projeto Ant faz uma substituição usando expressões regulares em diversas linhas de um arquivo:

<project name="MeuProjeto" default="substituicao" basedir=".">
    <target name="substituicao">
        <replaceregexp
                file="${file}"
                byline="true"
                match="meu nome é (\w+)"
                replace="me chamo \1"
                flags="gs" />
    </target>
</project>

A tag <project> declara o projeto atual e seus atributos básicos. Ela deve ser a raiz do arquivo. O atributo default indica qual target será executado se nenhum outro for informado via linha de comando. O atributo basedir define o diretório base onde as tarefas serão executadas.

A tag <target>, por sua vez, declara um conjunto das atividades. Nesse caso, temos apenas a task <replaceregexp>.

Note o valor do atributo file da nossa task: ${file}. A cifra com as chaves de abertura e fechamento é algo similar à expression language do JSP, só que bem simplificada, tratando-se de uma interpolação de propriedades simples. O Ant substitui essa expressão por um valor definido anteriormente, de forma análoga a uma variável. Porém, não declaramos isso em lugar algum, então o valor terá que ser informado via linha de comando.

Executando o Projeto

Ao ser executado, o Ant procura automaticamente por um arquivo chamado build.xml no diretório atual. Então, se file.txt é um arquivo a ser processado pelo nosso build, o comando a seguir irá realizar a substituição:

ant -Dfile=file.txt

Caso o projeto Ant tenha outro nome, pode-se usar o parâmetro -f:

ant -f /caminho/meu-build.xml -Dfile=file.txt

O que o Ant pode fazer

O Ant possui muitas tasks prontas, dentre as quais posso destacar:

  • Javac: compila classes Java.
  • Sshexec: executa comandos remotos via SSH.
  • Copy: copia um ou mais arquivos, possibilitando filtrar o conteúdo e substituir trechos do mesmo.
  • Jar, War, Ear: empacota arquivos em uma dessas estruturas.

Além disso, o Ant possui alguns pontos de extensão. Por exemplo, você pode criar tasks personalizadas ou até seu próprio interpolador de variáveis.

Note que o Ant não é uma linguagem procedural e não tem comandos de controle. Entretanto, existe um projeto chamado Ant Contrib que disponibiliza tasks adicionais como If, For e TryCatch. Isso vai um pouco contra a filosofia do Ant, mas pode ajudar seus build a serem mais poderosos.

Outro projeto que estende o Ant chama-se Flaka. Ele acrescenta uma expression language muito mais poderosa que a original, estruturas condicionais, tratamento de exceções e muitas tasks.

Aprendendo mais sobre o Ant

Minha dica é: apenas leia o manual todo, começando pela seção Writing a simple Buildfile. Ele não é muito extenso e explica bem os conceitos.

Entenda bem os conceitos gerais antes de usar as extensões mencionadas no tópico anterior a fim de evitar surpresas.

Ainda vale a pena usar o Ant se há outras opções para build?

Sim e não.

Hoje temos o Maven, por exemplo, que gerencia o ciclo de vida de um projeto, da compilação à publicação, de forma padronizada. Porém, a arquitetura dos builds Maven também limita a execução de atividades arbitrárias que são necessárias em alguns projetos. Por isso, quem conhece Ant pode usar o Maven Antrun Plugin para executar tarefas personalizadas em qualquer fase do processo de build. É muito mais simples que criar e manter, por exemplo, um plugin próprio para o Maven.

Outra ideia é criar tasks independentes de projetos. Por exemplo, para automatizar um processo batch executado no servidor ou mesmo uma tarefa repetitiva no ambiente de desenvolvimento, como compilação de relatórios JasperReports.

Por outro lado, não fique preso a uma única ferramenta. Procure ter um conhecimento geral sobre ferramentas de build como Ant, Maven, Graddle, Ivy e outros semelhantes. Em geral, é melhor ter um canivete suíço do que um facão grande para fazer tudo. 😉


Este artigo foi baseado na minha resposta no StackOverflow em Português!

Creative Commons O blog State of the Art de Luiz Ricardo é licenciado sob uma Licença Creative Commons. Copie, compartihe e modifique, apenas cite a fonte.