segunda-feira, 9 de dezembro de 2013

C++ e Maven: nar-maven-plugin

No meu trabalho, desenvolvo códigos em C, C++ e Java principalmente, além de outras linguagens. Para Java, já não consigo mais dispensar a utilização do Maven. Pesquisei sobre como usar Maven também para compilar códigos em C e C++. Foi então que encontrei o nar-maven-plugin.

Este plugin para Maven está atualmente ativo graças a uma grupo de desenvolvedores, mas nem sempre foi assim: ele esteve meio parado por um tempo e seu desenvolvedor original doou o código para um outro grupo de desenvolvedores continuar o trabalho. Tutoriais sobre o plugin ainda são escassos e muitos fazem referência a uma versão mais antiga e algumas configurações não se aplicam mais para a versão atual. O mailing list no momento tem poucas postagens, mas quando o assunto é relevante, os desenvolvedores estão sempre atentos e respondem com rapidez.

Uma outra opção é usar o native-maven-plugin. Este tem a sua última versão, a 1.0-alpha-7, liberada em março de 2011. Os tutoriais sobre este plugin são poucos e achei sua configuração pouco intuitiva. Por todos estes motivos desfavoráveis, optei por usar o nar-maven-plugin, principalmente por estar mais ativo no momento e ser mais um pouco mais fácil configurá-lo.

Objetivos dos Testes

A intenção aqui é criar dois projetos em C++, sendo um para gerar uma biblioteca estática e outro com uma biblioteca dinâmica que utiliza a biblioteca estática.

Os projetos são bem simples e estão estruturados de acordo com Maven 3. O foco está na utilização do nar-maven-plugin e não exatamente na utilização do Maven. Portanto, é esperado que se conheça o básico sobre Maven e sua utilização.

Preparação para os Testes

Os testes foram realizados no Windows 7 64 bits utilizando os seguintes sistemas:
  • Maven 3
  • Mingw 4.8.1
  • Nar-maven-plugin-3.0.0
    Tanto para o Maven quanto para o Mingw, os diretórios de instalação (com \BIN) devem ser incluídos manualmente no PATH do Windows.

    O nar-maven-plugin será baixado automaticamente pelo Maven de acordo com a configuração apresentada abaixo.

    Download

    O código dos projetos usados para testes estão disponíveis para download. São simples mas servem de modelo para evoluir para projetos maiores.


    Projeto Biblioteca Estática

    Este projeto serve de base para os demais. Abaixo, o arquivo pom.xml do projeto da biblioteca estática é apresentado com a configuração mínima para a utilização do nar-maven-plugin.

    <project xmlns="http://maven.apache.org/POM/4.0.0" 
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>prototype</groupId>
        <artifactId>lib-project</artifactId>
        <version>1.0-SNAPSHOT</version>
      
        <!-- Importante que a opção JAR seja substituída por NAR -->
        <packaging>nar</packaging>
    
        <name>lib-project</name>
    
        <!-- Repositório onde está armazenado o plugin -->
        <pluginRepositories>
            <pluginRepository>
                <id>Sonatype OSS</id>
                <url>http://oss.sonatype.org/content/groups/public</url>
            </pluginRepository>
        </pluginRepositories>
    
        <build>
            <plugins>            
                <plugin>
                    <groupId>com.github.maven-nar</groupId>
                    <artifactId>nar-maven-plugin</artifactId>
                    <version>3.0.0</version>
                    <extensions>true</extensions>
                    <configuration>
                        <!-- Importante definir o nome do compilador C++ caso não seja 
                             o default definido pelo NAR plugin de acordo com a plataforma. 
                             No caso da plataforma Windows, o default é o
                             Microsoft Visual C++. -->                                                                                                   
                        <cpp>                                                        
                            <name>g++</name>  
                        </cpp>
                        <!-- Idem para o linker -->             
                        <linker>
                            <name>g++</name>
                        </linker>
                        <!-- Definir o tipo de binário gerado, neste caso uma biblioteca estática -->
                        <libraries>
                            <library>
                                <type>static</type>
                            </library>
                        </libraries>                    
                    </configuration>                
                </plugin>
            </plugins>
        </build>
        
    </project>
    

    Alguns pontos devem ser observados aqui sobre o arquivo pom.xml:
    1. A configuração de packaging deve ser alterada de JAR para NAR (em letras minúsculas lá no XML), caso contrário o plugin não funcionará;
    2. A localização do repositório do plugin deve ser especificada; desde dezembro de 2013, o plugin tem sido armazenado no Sonatype OSS.
    3. O compilador padrão do plugin é de acordo com a plataforma: para Windows, o padrão é o Microsoft Visual C++ e portanto, caso o exemplo seja utilizado com este compilador, não é necessário definir o nome. Como o exemplo aqui está usando o Mingw, temos que definir o nome do compilador e linker como mostra a configuração no arquivo XML.
    4. Determinar o tipo de arquivo binário gerado, nesta caso uma biblioteca estática.
    Ainda, vale a pena citar a estrutura de arquivos que o plugin espera: por convenção, os arquivos fontes devem estar na pasta \src\main\c++ e os arquivos *.H que acompanham a biblioteca estática (e usados pela biblioteca dinâmica) devem para estar na pasta \src\main\include. É possível modificar ou acrescentar novas pastas. Consulte as opções de configuração oferecidas pelo plugin no site do projeto.

    Uma vez a compilação ocorra com sucesso, o plugin compacta a biblioteca estática e todos os arquivos contidos na pasta \src\main\include do projeto num único arquivo com a extensão NAR e os instala no repositório maven local.

    Projeto Biblioteca Dinâmica

    O arquivo pom.xml deste projeto é basicamente o mesmo do projeto anterior, com alteração no tipo de binário gerado e incluindo a dependência do projeto anterior para 'linkar'.

    <project xmlns="http://maven.apache.org/POM/4.0.0" 
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>prototype</groupId>
        <artifactId>shared-project</artifactId>
        <version>1.0-SNAPSHOT</version>
      
        <packaging>nar</packaging>
    
        <name>shared-project</name>
    
        <!-- Repositório onde está armazenado o plugin -->
        <pluginRepositories>
            <pluginRepository>
                <id>Sonatype OSS</id>
                <url>http://oss.sonatype.org/content/groups/public</url>
            </pluginRepository>
        </pluginRepositories>
    
        <dependencies>
            <!--  dependência do projeto biblioteca estática  -->
            <dependency>           
                <groupId>prototype</groupId>
                <artifactId>lib-project</artifactId>
                <version>1.0-SNAPSHOT</version>
                <!-- Importante definir o tipo como NAR -->
                <type>nar</type>
            </dependency>
        </dependencies>
      
        <build>
            <plugins>            
                <plugin>
                    <groupId>com.github.maven-nar</groupId>
                    <artifactId>nar-maven-plugin</artifactId>
                    <version>3.0.0</version>
                    <extensions>true</extensions>
                    <configuration>                                                
                        <cpp>                                                        
                            <name>g++</name>  
                        </cpp>             
                        <linker>
                            <name>g++</name>
                        </linker>
                        <!-- Gera binário como biblioteca dinâmica -->
                        <libraries>
                            <library>
                                <type>shared</type>
                            </library>
                        </libraries>                    
                    </configuration>                
                </plugin>
            </plugins>
        </build>
        
    </project>
    

    Note que os arquivos *.H da biblioteca estática não precisam ser colocados explicitamente no projeto, conforme explicado anteriormente. Ao compilar um projeto que use esta dependência, o plugin descompacta o arquivo NAR da biblioteca estática e automaticamente inclui os arquivos *.H no caminho de pesquisa para o compilador. O mesmo acontece com o binário da biblioteca estática usado pelo linker.

    Considerações Finais

    A configuração do arquivo pom.xml para compilar código em C++ é muito simples com o nar-maven-plugin.

    O nar-maven-plugin recentemente voltou a ser mantido por um grupo de desenvolvedores e seu mailing list está ativo.

    A utilização do plugin é mais interessante quando se tem código Java que faz acesso código em C++ (ou em C) via JNI; o plugin é capaz de gerar automaticamente os headers e compilar juntos tanto o código Java quando o código em C++. Vou apresentar uma exemplo no próximo artigo.

    quinta-feira, 21 de março de 2013

    Layout Ajax com JSF

    Esta informação está contida em outros blogs mas decidi escrevê-la aqui também porque sempre achei informações incompletas, sendo um pouco num blog e outro pouco noutro.

    A ideia é criar um layout de website com área de cabeçalho, menu à esquerda e centro com conteúdo. Até aí é fácil e o Netbeans dá uma mão para a gente (na versão 7.3, crie um facelet e você verá). Neste layout, a intenção é permitir que o usuário clique no menu posicionado à esquerda e o conteúdo da página (no centro) seja atualizado sem que toda a página seja recarregada.

    Primeiro, é necessário criar um controlador (bean) para manter a página corrente a ser carregada. Veja, no código abaixo, a declaração bem simples do IndexController;  perceba que o atributo currentPage é inicializado com o nome da página com o conteúdo inicial do site.

    @ManagedBean
    public class IndexController {
    
        private String currentPage = "home.xhtml"; // página com conteúdo inicial
    
        public String getCurrentPage() {
            return currentPage;
        }
    
        public void setCurrentPage(String currentPage) {
            this.currentPage = currentPage;
        }
    }
    

    Supondo que a página inicial seja index.xhtml, com o layout do site devidamente estruturado (junto com CSS), insira o código abaixo na área reservada para a descrição do menu. Aqui, o menu está bastante simples e é basicamente composto por dois links onde cada um deve abrir as páginas inserir.xhtml e listar.xhtml.

    <h:form>
       <f:ajax render=":contentForm:reload">
          <h:commandlink action="#{indexController.setCurrentPage('inserir.xhtml')}" value="Inserir"/>
          <h:commandlink action="#{indexController.setCurrentPage('listar.xhtml')}" value="Listar"/>
       </f:ajax>
    </h:form>
    

    Ainda no mesmo arquivo index.xhtml, agora na área reservada para o conteúdo do website propriamente dito, insira o código abaixo.

    <h:form id="contentForm">
        <h:panelGroup id="reload">
            <ui:include src="#{indexController.currentPage}"/>
        </h:panelGroup>
    </h:form> 

    Os códigos demonstrados acima fazem referência à 3 arquivos: home.xhtml, inserir.xhtml e listar.xhtml. Estes arquivos precisam ser criados com o conteúdo específico. Abaixo está o exemplo de como tais arquivos devem ser criados:

    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets">
        <ui:composition>
             Coloque aqui o conteúdo a ser exibido no website! 
        </ui:composition>
    </html>
    

    Com esta abordagem, a URL do website não modifca toda vez que o usuário clica no menu!

    Agora suponha que o conteúdo exibido no website tenha um botão ou um link que leve à outra página. Naturalmente a ideia aqui é atualizar comente a área de conteúdo. O código abaixo mostra um exemplo de como seria isto:

    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:ui="http://java.sun.com/jsf/facelets"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:f="http://java.sun.com/jsf/core">
        <ui:composition>
            <f:ajax render=":contentForm:reload">
                <h:commandLink value="Atualizar" action="#{indexController.setCurrentPage('/ui/alterar.xhtml')}"/>               
            </f:ajax>
        </ui:composition>
    </html>
    

    Veja que no código acima não está declarado a tag <h:form> para permitir a declaração do <h:commandLink>. Aqui, o form com o identificador 'contentForm' já fora delcarado em index.html e recebe toda a atualização da página e por isso não precisa ser declarado novamente.

    Referências:

    sexta-feira, 25 de janeiro de 2013

    Problema com Placa de Vídeo na Atualização do Windows 8

    Após a atualização do meu notebook para Windows 8, a placa de vídeo AMD Radeon não foi instalada corretamente e frequentemente apresentava erro no aplicativo ATI Catalyst Control Center.

    O gerenciador de dispositivos exibia o problema na placa de vídeo cujo nome era AMD Radeon HD 7000M. Baixei seu driver direto do site da Sony e também direto do site da AMD, todos sem sucesso.

    Todavia, meu notebook tem um aplicativo da Sony que faz atualização do sistema como um todo. Resolvi usar este aplicativo e para a minha surpresa, foi identificada uma outra versão da placa de vídeo sendo a AMD Radeon HD 6470M / 6630M.

    Devido a este erro no nome da placa de vídeo apresentado pelo gerenciado de dispositivos do Windows 8, eu erroneamente estava baixando e instalando a versão errada do driver da AMD Radeon HD.

    Fica aí a dica para aqueles que estão com o mesmo problema.

    Atualização para Windows 8

    Como profissional da área de tecnologia da informação, tenho a obrigação de experimentar as novidades do mercado, à medida do possível. Próximo do final do mês de janeiro de 2013, data limite para término da promoção de atualização do para o Windows 8, resolvi experimentar e mal sabia o que viria pela frente.


    Até então, estava com o Windows 7 Professional e Office 2010, tudo legalizado. Por causa do Office 2010, o Thunderbird (cheio de mensagens de e-mail de várias contas), outros softwares que adquiri e outros tantos gratuitos que estavam devidamente configurados, resolvi fazer a atualização para Windows 8 com a opção para manter dados de usuário e aplicativos instalados. O assistente de atualização da Microsoft indicava que somente um aplicativo não era compatível; então, comprei a licença do Windows 8 e comecei a instalação.

    Após longos minutos esperando a finalização do download, a instalação começou, foi até 90% e reiniciou a máquina. Para minha surpresa (que ingênuo!), houve uma mensagem após o reinício indicando "falha na instalação do Windows". O sistema recuperou a instalação do Windows 7 sem problemas (ufa!), mas não deu nenhum indicativo do problema encontrado.

    Vasculhei fóruns, inclusive em inglês, e encontrei uma legião de usuário do Windows na mesma situação com a mesma mensagem de erro, porém somente alguns mais insistentes conseguiram resolver o problema, mas cada um de uma forma diferente. Segui algumas dicas, mas continuei com a mesma mensagem de erro após tentar novamente e algumas vezes mais.

    Encontrei um artigo no site da Microsoft chamado "Noções Básicas de Falhas e Arquivos de Logs", onde entendi como poderia localizar arquivos de registros da instalação do Windows 8. Os arquivos não fornecem muitas informações objetivas para usuários, ou seja, eles podem servir para alguma coisa para o pessoal de desenvolvimento de suporte da Microsoft, mas não muito para nós. No meu caso, explorei o arquivo setuperr.log e entendi  que o erro era porque o sistema não localizava um determinado arquivo no sistema.Veja abaixo alguns registros de erro:

    2013-01-23 20:37:33, Error                 CONX   [CDeviceBiosBlocks::Generate] Unable to open SDB C:\Users\ALEXAN~1\AppData\Local\Temp\8f2f2112-0329-428a-bb95-b48bc77e51d0\WebSetupExpanded\drvmain.sdb.[gle=0x000000cb]
    2013-01-23 20:37:33, Error                 CONX   [wmain] [0x80004005] QueryAppBlock encountered an error gathering bios blocks.
    2013-01-23 20:37:33, Error                 CONX   [ConX::Compatibility::Wica::GetCompatibilityInfo] Query bios block returned an error - 1.[gle=0x00000715]
    

    Pelo caminho e nome do arquivo indicado no registro, verifiquei que o arquivo não existia mesmo no meu sistema.

    Apelei então para a instalação usando mídia de DVD. O assistente de atualização permite que seja gerado um arquivo no formato ISO para depois gerar a mídia de instalação. Aqui, é necessário ter um software adequado para gravar o arquivo ISO como um DVD (eu tenho o Ashampoo Burning Studio). Comecei agora a instalação pelo DVD e consegui avançar; o error gerado antes não mais surgiu, todavia um novo problema surgiu no mesmo estilo do anterior: "falha na instalação do Windows", sem mais detalhes. Abri de novo o mesmo arquivo de registros de erro e identifiquei um novo problema:

    2013-01-24 21:57:27, Error                        Error READ, 0x0000000B while gathering/applying object: File, C:\Users\Alexandre\AppData\Local\Microsoft\Windows Mail. Will return 0
    2013-01-24 21:57:27, Error                 MIG    Error 11 while applying object C:\Users\Alexandre\AppData\Local\Microsoft\Windows Mail. Shell application requested abort
    2013-01-24 21:57:27, Error      [0x08097b] MIG    Abandoning apply due to error for object: C:\Users\Alexandre\AppData\Local\Microsoft\Windows Mail
    2013-01-24 21:57:28, Error                        pUpgLayerDoOnlineApply: Apply operation failed. Error: 0x0000002C
    

    O máximo que entendi destes registros de erro tudo foi um problema qualquer na pasta de dados de aplicativo do Windows Mail. Nem sabia o que era isso, mas supus que fosse alguma coisa ligada ao Windows Live, o qual desinstalei imediatamente, uma vez que ele também não é compatível com o Windows 8. Ainda, fui bisbilhotar a pasta indicada no registro de erro e percebi que ela estava diferente das outras, com as letras (fonte) em verde. Esta característica indicava que a pasta estava criptografada (o Windows 7 Professional permite isso, mas não as versões inferiores do mesmo Windows). Desfiz a criptografia e comecei novamente a atualização para Windows 8.

    Finalmente consegui completar a instalação e configuração do Windows 8, depois de vários dias e muitas horas de persistência e paciência. A fabricante do meu notebook (Sony) disponibilizou um pacote de drivers para Windows 8, além de um excelente tutorial de como fazer a migração para Windows 8; baixei o pacote e fiz a instalação. Vale aqui um elogio para a Sony pela facilidade em localizar, baixar e instalar todos os drivers para meu notebook.

    Quanto a Microsoft, fica o desapontamento quanto ao suporte técnico; nos fóruns da própria empresa, nenhuma dica realmente útil vinda dos próprios profissionais da Microsoft. As  informações relevantes geralmente têm sido publicadas pelos próprios usuários do sistema que conseguiram resolver alguns dos problemas encontrados.

    Quanto ao Windows 8, me acostumei rápido com a nova interface gráfica e achei o sistema um pouco mais rápido, comparado ao Windows 7. Os aplicativos instalados anteriormente parecem realmente compatíveis com o novo sistema operacional; estava especialmente preocupado com o Office 2010, pois é uma versão de 32 bits num sistema de 64 bits e encontrei vários relatos de incompatibilidade - por sorte, não foi o meu caso!

    segunda-feira, 23 de julho de 2012

    IceScrum?

    IceScrum é uma ferramenta interessante para gerenciamento do processo ágil de desenvolvimento de software chamado Scrum. Desenvolvido em Java na plataforma web, o IceScrum é um software de código aberto e grátis (download).

    Entre algumas ferramentas grátis que testei para auxiliar no gerenciamento do processo de desenvolvimento, o IceScrum foi a ferramenta que me deixou mais confortável porque implementa os conceitos da metodologia Scrum de forma concisa e quase natural.

    Instalação & Configuração

    A instalação da ferramente pode ser feita pela implantação de um arquivo WAR no Tomcat, ou noutro servidor compatível, ou então baixar a versão 'bundled' que já vem com o Tomcat embutido e executar scripts para execução.

    A versão atual  R5#1.2 dispensa maiores configurações para banco de dados, pois utiliza o banco de dados embutido HSQLDB, também baseado em Java. Apesar desta facilidade, outras configurações ainda são necessárias e as instruções apresentada no site não são tão precisas. Tive problemas com as duas opções de instalação, mas consegui colocar em funcionamento apenas a versão 'bundled' após diversas tentativas (mas isso está fora do escopo deste artigo). O fórum de suporte da ferramenta ajudou, mas tem várias respostas dos próprios administradores do fórum sem explicações técnicas sobre o problema, apenas indicando um download para resolvê-lo.

    Funcionalidades

    Mesmo não registrado no sistema (logado), qualquer pessoa pode visualizar parcialmente os projetos cadastrados. Esta visualização parcial significa ver o painel inicial do projeto, os registros de atividades e incluindo os gráficos, a área livre (sandbox) e a lista do produto (product backlog); também é possível ver a estórias detalhadamente.

    Ainda, qualquer pessoa que acessa o sistema pode fazer um registro, criar um projeto e montar uma equipe para este projeto adicionando usuários cadastrados na ferramenta ao projeto.

    Somente após pesquisar no fórum de discussão da ferramenta, descobri que existe um usuário administrador. Este usuário consegue acessar todos os projetos, aparentemente sem restrição, mas não tem o controle dos usuários cadastrados. Isso chegou a ser um problema para mim, pois, aqui, um desenvolvedor chegou a esquecer a identificação e senha da própria conta; eu não tive como pesquisar a sua identificação no sistema, para que mais tarde, o próprio usuário pudesse fazer a sua recuperação de senha.

    Gostei bastante da possibilidade de criar estórias por qualquer membro da equipe, ficando estas estórias numa área livre esperando aceitação do dono do projeto ou scrum master. Uma estória pode ser priorizada e também estimadas por 'story points' após aceita. Também é possível adicional testes de aceitação à estórias.

    As iterações são programadas de forma fácil, onde as estórias aceitas e estimadas (atribuição de peso) são listadas e adicionadas à iteração via drag-and-drop. A partir de uma estória, criam-se as tarefas que automaticamente assumem a coluna 'Para Fazer' do painel de iteração.

    A imagem ao lado mostra o painel de um projeto em andamento; nomes de projeto, de algumas tarefas e de colaboradores foram ofuscados por motivos óbvios! Os post-its das tarefas apresentados no painel podem ser movidos entre as colunas  'Para Fazer', 'Em Andamento' e 'Concluído' via drag-and-drop

    Os desenvolvedores do projeto devem mover uma tarefa com estado 'Para Fazer' para a coluna 'Em Andamento'; automaticamente o sistema associa o desenvolvedor à tarefa. Uma vez a tarefa concluída, o post-it deve ser movido para a coluna seguinte. Muito intuitivo!

    Problemas...

    Uma desvantagem da ferramenta é a quantidade de memória alocada para sua execução. O tamanho de 512 MB é a quantidade mínima recomendada, mas eu tive que alocar um pouco mais. Para fazer isso na versão 'bundled' foi preciso modificar os scripts de execução do Tomcat, o que não está prontamente documentado no site da ferramenta!

    Em alguns momento, a ferramenta travou, mesmo com mais de 512MB de memória alocada. Apenas dois projetos com pouquíssimas estórias e tarefas estavam cadastradas na ferramenta. Ainda estou acompanhando e analisando a frequência deste tipo ocorrência.

    Ainda, mensagens de erro com a conexão com banco de dados foi apresentada, todavia não foi notado maiores problemas além da mensagem.

    Conclusão

    IceScrum, versão R5#1.2, é uma ferramenta com uma interface gráfica agradável e até um tanto intuitiva. Sua instalação não foi tranquila para mim e a documentação do site está desatualizada; todavia o fórum de discussão pode ajudar. A alocação de memória superior se comparada à outras ferramentas não chega a ser um impeditivo real, já os problemas de travamento da ferramenta e mensagem de erro de conexão com o banco de dados deixa uma impressão ruim e uma sensação de insegurança para adotar a ferramente integralmente. 

    segunda-feira, 2 de julho de 2012

    Configurando Launch4J para Maven

    Launch4J é um aplicativo famoso usado para transformar arquivos JAR em arquivos executáveis para o sistema operacional Windows. É natural que se queira utilizar este aplicativo em conjunto com o Maven para gerar os arquivos finais do projeto para distribuição. Neste cenário, a intenção é atualizar sempre o número da versão e build do aplicativo automaticamente, antes mesmo de gerar o arquivo executável.

    A primeira opção para rodar o Launch4J integrado ao Maven é a utilização de plugin. Nos links de referência, no final deste artigo, estão listados alguns websites para o plugin Launch4J para Maven e outros links com exemplos de uso.

    A utilização do plugin pode ser mais limitada (ainda não testei) e ainda talvez se deseja utilizar a configuração já existentes do Launch4J do projeto, sem correr o risco de perder alguma configuração; este motivo justificaria a utilização do Launch4J era como um tarefa do Ant.  Não vou ensinar como criar este arquivo de configuração, pois já está razoavelmente documentado no próprio website do Launch4J. Assim, com um mínimo de adaptação, o Launch4J fica pronto para o Maven, como uma tarefa do Ant, como mostra o código abaixo:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-antrun-plugin</artifactId>
        <executions>
            <execution>
                <id>launch4j</id>
                <phase>package</phase>
                <goals>
                    <goal>run</goal>
                </goals>
                <configuration>
                    <tasks>                                
                        <copy file="config.xml" tofile="config-temp.xml"/>                                
                        <replace file="config-temp.xml" token="0.0.0.0" value="${project.version}.${BUILD_NUMBER}"/>
                        <taskdef name="launch4j" classname="net.sf.launch4j.ant.Launch4jTask" classpath="${launch4j.dir}/launch4j.jar:${launch4j.dir}/lib/xstream.jar" />
                        <launch4j configFile="./launch4j-client-temp.xml" jar="${project.build.directory}\my-application-${project.version}.jar" outfile="${project.build.directory}\my-application.exe"/>
                        <delete file="${project.build.directory}\my-application-${project.version}.jar"/> 
                        <delete file="config-temp.xml"/>
                    </tasks>
                </configuration>
            </execution>
        </executions>
    </plugin> 
    

    Aqui, utilizei o plug-in Antrun.  Da linha 13 à linha 18 estão as configurações das tarefas Ant para execução.

    A linha 13 copia o arquivo de configuração do Launch4J para um arquivo temporário, que é manipulado na sequência (linha 14). Neste arquivo, todas as sequências de caracteres 0.0.0.0 serão substituídas pelo número da versão do projeto (variável do próprio Maven: ${project.version}) e o número da build (variável do Hudson: ${BUILD_NUMBER}). Só lembrando, caso não esteja trabalhando com o Hudson, você deve remover esta última variável da composição dos números da versão do seu aplicativo.

    A definição da tarefa do Launch4J é feita na linha 15. Pressupõe-se que o aplicativo esteja instalado no ambiente de execução do Maven. Aqui, a variável ${launch4j.dir} fora definida anteriormente no arquivo pom.xml do projeto com o caminho da instalação do aplicativo. Observe que tal variável aparece duas vezes no atributo 'classpath' desta linha.

    Na sequência, linha 16, vem a chamada da própria tarefa definida da linha anterior. Esta tarefa demanda 2 atributos, sendo o nome do arquivo JAR e o nome do executável que será gerado. As variáveis utilizadas aqui são do próprio Maven.

    As linhas 17 e 18 fazem uma limpeza: remove o arquivo JAR, que agora já está encapsulado como um arquivo executável, e depois remove o temporário criado na linha 13.

    Conclusão

    A solução apresentada para se trabalhar com Launch4J e Maven atende aqueles que estão começando a trabalhar tanto com um ou outro destes aplicativos, sem exigir muita configuração por parte Maven. O plugin Antrun utilizado para fazer toda a configuração é da Apache e portanto se espera uma compatibilidade com as futuras versões do próprio Maven, facilitando assim uma possível atualização de versão.

    Referências

    http://launch4j.sourceforge.net/
    http://ant.apache.org/
    http://9stmaryrd.com/tools/launch4j-maven-plugin/
    http://mvnrepository.com/artifact/com.akathist.maven.plugins.launch4j/launch4j-maven-plugin
    http://stackoverflow.com/questions/6060560/trying-to-integrate-launch4j-in-a-maven-project-using-alakai-plugin

    Jogo da Memória em JavaFX 2.1

    Aqui, disponibilizo o código fonte de um jogo da memória feito em JavaFX 2.1. O código foi desenvolvido pelo NetBeans 7.1.1. O arquivo compactado contém todo o código fonte, arquivos e áudio e um arquivo JAR que consiste no jogo pronto para ser executado. Ao clicar no botão ou no link para download, você será direcionado para o Google Drive e todos os arquivos do projeto serão listados. Para fazer efetivamente o download, tecle CTRL+S ou vá no menu 'File' e selecione a opção 'Download' para fazer um único download de todos os arquivos.

    Vale lembrar que para compilar o jogo, você precisa do JDK 6 ou superior com o módulo para JavaFX, que pode ser baixado pelo site da Oracle. Se você possui o JDK 7 atualizado, então o JavaFX já está incorporado.

    No código deste jogo, vocês verão a criação de formas, aplicação de transformações e efeitos, animação sincronizada com áudio e interação com usuário. Tudo isso já foi descrito nos artigos anteriores, de forma didática.

    Este jogo da memória é baseado naquele famoso jogo eletrônico da década de 80 chamado Genius. Nesta implementação, a lógica basicamente é a repetição pelo usuário de uma sequência determinada pelo jogo. A sequência pode ser mais rápida ou mais lenta, até atingir uma sequência de 10, começando sempre com 4.

    Durante o jogo, é sempre informado a sequência criada pelo sistema e quando o usuário deve iniciar sua interação. As mensagens são sempre exibidas no centro do círculo e desaparecem após 3ms com efeito de 'fading'.

    Ao iniciar o jogo, o botão fica desabilitados até a sua finalização. Todavia, o controle para modificar a velocidade do jogo continua habilitado.

    A sequência criada pelo jogo é apresentada ao usuário pela animação de cada quarto de círculo, causando a sensação de que fora ligado/aceso e depois apagado. Aqui foi usado o RadialGradient para produzir o efeito desejado, ou seja, para que mais ou menos no centro de cada forma fosse mais claro e no restante mais escuro. Ainda, para cada cor do círculo existe um som associado, executado de forma síncrona com a animação.

    Durante a exibição automática da sequência criada pelo jogo, o usuário não tem como interagir com o sistema (exceto mudando a velocidade do jogo).

    Após ser informado pelo jogo, com a mensagem 'Sua vez!', o usuário pode então tentar repetir a sequência criada. Não foi criado um tempo limite (timeout) para início da interação do usuário.

    Caso o usuário erre a sequência exibida pelo jogo, um som, uma mensagem e efeito de 'fading' do círculo e da mensagem são executados paralelamente. Após 3ms, o jogo volta ao estado inicial, habilitando o botão inciar, pronto para um novo jogo.

    Se o usuário conseguir repetir a sequência de 10, sem errar, o jogo também emite som, exibe mensagem e um efeito de rotação de 360 graus horário. Da mesma forma, após 3ms, o jogo volta ao estado inicial, habilitando o botão inciar, pronto para um novo jogo.


    Para finalizar, não posso deixar de referenciar o artigo de João Paulo chamado "Genius em C#". Neste artigo, o autor também disponibiliza o código-fonte do seu jogo, junto com arquivos de áudio. Estes mesmos arquivos de áudio são utilizados neste exemplo em JavaFX.