Category: Web



Olá pessoal. Sempre quando começo um novo projeto que tenho que usar relatórios, eu procuro sempre automatizar o processo de compilação dos mesmos. Para quem não sabe, o NetBeans utiliza o Apache Ant (parecido com o make do C/C++) para executar o build do projeto, ou seja, é o Ant que faz a mágica de compilar os arquivos .java, copiar determinados arquivos para algum diretório, criar o pacote de distribuição e assim por diante. Além do comportamento padrão do Ant para cada tipo de projeto, podemos inserir trechos de código no arquivo de build para que tarefas personalizadas possam ser executadas durante o processo de build.

Sendo assim, hoje vou ensinar como personalizar esse arquivo de build de forma a fazer com que sempre que nosso projeto for executado, sejam compilados os arquivos de código fonte dos relatórios (.jrxml), fazendo com que nosso projeto SEMPRE contenha a versão compilada que corresponde a última versão da definição dos relatórios. Com isso, evitamos ter que ficar compilando manualmente os relatórios a cada vez que alterarmos um arquivo.

Vou usar como base o projeto finalizado na Parte 4 do tutorial sobre relatórios. Clique aqui para fazer o download do projeto. Como nosso projeto é desktop, vou abordar com mais detalhes a personalização do arquivo de build para esse tipo de projeto, mas no final do tutorial eu vou postar o trecho de código para o arquivo de build de um projeto Web. Então vamos lá!

Primeiramente, abra o projeto no NetBeans. Ao abri-lo, verifique que por padrão a aba “Projects” tomará o foco. Ao lado desta aba, existe a aba “Files”. Nessa aba é mostrada a estrutura real do projeto, ou seja, a estrutura de diretórios e arquivos que ficam armazenada no seu computador, enquanto na aba “Projects” é mostrada uma estrutura abstrata do projeto que esconde os detalhes da estrutura real. Veja a Figura abaixo.

Figura 1

Estrutura real do projeto

Note que destaquei dois arquivos na estrutura. O arquivo build-impl.xml é gerado automaticamente pela IDE, então mesmo que você o altere ela vai regerá-lo sempre. Sendo assim, nunca mexa nesse arquivo. Use-o para ver como o início do processo de build padrão funciona. O outro arquivo destacado, o build.xml, é o arquivo que podemos alterar para inserir nossas tarefas de build personalizadas. Durante o processo de build, o Ant copia os targets configurados no build-impl.xml para o build.xml, para então executar o arquivo de build.

Recomendo que vocês leiam todos os comentários que são criados dentro do build.xml. Neles vocês terão uma ideia de como o processo funciona. Notem que logo no início, são listados vários targets que podemos personalizar: -pre-init, -post-init, -pre-compile, etc. O nome de cada target é auto-explicativo, além é claro de ter o comentário explicando quanto eles são executados. Falei dos targets várias vezes, mas ainda não expliquei o que eles são. Um target é como se fosse um “passo” no processo de build. Você pode ter um ou vários passos durante o processo de build e cada passo pode depender de um ou vários passos que foram executados anteriormente. Por exemplo, um target que faz o empacotamento do projeto em um .jar, depende do target que faz a compilação dos arquivos .java.

No nosso arquivo de build, nós vamos inserir tarefas dentro do target “-post-compile”, ou seja, o target que é executado depois que os arquivos .java do projeto são compilados. Segue o código do build.xml comentado.

build.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- Documentação (omitida) -->
<project name="TutorialRelatorios" default="default" basedir=".">
    <description>Builds, tests, and runs the project TutorialRelatorios.</description>
    <import file="nbproject/build-impl.xml"/>
    <!--

        Documentação (omitida)

    -->

    <!-- configurando o target -post-compile, que é executado depois
         da compilação dos arquivos .java do projeto-->
    <target name="-post-compile">

        <!-- Compilação das definições dos relatórios -->
        <!-- a tarefa "echo" do Ant mostra uma mensagem na saída -->
        <echo>Iniciando compilação das definições de relatórios...</echo>

        <!-- Define o classpath usado para a compilação dos relatórios -->

        <!-- A tarefa "path" do Ant define um caminho com id de "jrc.classpath"
             que indica um conjunto de arquivos (fileset) que correspondem
             a todos os .jars (que serão usados na compilação) localizados no
             diretório ${build.dir}/../lib/JasperReports-3.7.5.

             Quando o build for executado, a propriedade ${build.dir} será
             substituida por C:\<caminho>\TutorialRelatorios\build,
             sendo assim estamos acessando o diretório
             C:\<caminho>\TutorialRelatorios\lib\JasperReports-3.7.5, que no nosso
             projeto armazena todos os .jars utilizados pelo JasperReports.

             Para entender o que está acontecendo, sempre verifique a estrutura
             do projeto (na aba File). -->
        <path id="jrc.classpath">
            <fileset dir="${build.dir}/../lib/JasperReports-3.7.5"
                     includes="*.jar"/>
        </path>

        <!-- Definimos então uma tarefa customizada do Ant, chamada "jrc",
             que é implementada na classe net.sf.jasperreports.ant.JRAntCompileTask,
             que por sua vez é usada para compilar arquivos .jrxml

             Note que é necessário configurar o classpath para o Ant
             saber onde a classe está definida, além das possíveis dependências
             que ela utiliza. O classpath vem da tarefa "path" que configuramos
             anteriormente, ou seja, todos os .jars do diretório
             C:\<caminho>\TutorialRelatorios\lib\JasperReports-3.7.5 -->
        <taskdef name="jrc"
                 classname="net.sf.jasperreports.ant.JRAntCompileTask">
            <classpath refid="jrc.classpath"/>
        </taskdef>

        <!-- Quando testamos nossos relatórios, eles são compilados, gerando
             arquivos .jasper. O problema é as vezes nós alteramos o arquivo fonte
             e esquecemos de compilar. Sendo assim, caso existam definições de
             relatórios compiladas (que podem corresponder à versões antigas dos .jrxml's),
             a tarefa "delete" do Ant (definida abaixo) apaga todos os arquivos .jasper do diretório
             ${build.classes.dir} (C:\<caminho>\TutorialRelatorios\build\classes), ou seja,
             onde os arquivos .jasper são copiados durante o processo de build normal.
             -->
        <delete>
            <fileset dir="${build.classes.dir}" includes="*.jasper"/>
        </delete>

        <!-- Por fim, compilamos as definições de relatórios (.jrxmls contidos no diretório
             "relatorios") do nosso projeto, sendo que os arquivos compilados (.jasper)
             são gerados no diretório ${build.classes.dir}, ou seja, em
             C:\<caminho>\TutorialRelatorios\build\classes. Note que usamos a tarefa "jrc" que definimos
             acima e precisamos passar novamente o classpath definido na tarefa "path". -->
        <jrc srcdir="relatorios"
             destdir="${build.classes.dir}">
            <classpath
                refid="jrc.classpath"/>
            <include
                name="*.jrxml"/>
        </jrc>

        <!-- Legal, terminou o processo, definições compiladas -->
        <echo>Compilação das definições de relatórios finalizada!</echo>

    </target>

</project>

Sendo assim, copie o target listado acima para dentro do seu build.xml e salve o arquivo. Dê um “Clean and Build” no projeto (volte para a aba “Projects”, botão direito no projeto, “Clean and Build”), ou então clique no botão com um martelo e uma vassoura na barra de tarefas. Se tudo deu certo, a saída do NetBeans vai ser essa aqui:

init:
deps-clean:
Updating property file: C:\<caminho>\TutorialRelatorios\build\built-clean.properties
Deleting directory C:\<caminho>\TutorialRelatorios\build
clean:
init:
deps-jar:
Created dir: C:\<caminho>\TutorialRelatorios\build
Updating property file: C:\<caminho>\TutorialRelatorios\build\built-jar.properties
Created dir: C:\<caminho>\TutorialRelatorios\build\classes
Created dir: C:\<caminho>\TutorialRelatorios\build\empty
Compiling 4 source files to C:\<caminho>\TutorialRelatorios\build\classes
Copying 5 files to C:\<caminho>\TutorialRelatorios\build\classes
Iniciando compilação das definições de relatórios...
Compiling 5 report design files.
log4j:WARN No appenders could be found for logger (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
log4j:WARN Please initialize the log4j system properly.
File : C:\<caminho>\TutorialRelatorios\relatorios\ClientesPorNome.jrxml ... OK.
File : C:\<caminho>\TutorialRelatorios\relatorios\ClientesCollectionDS.jrxml ... OK.
File : C:\<caminho>\TutorialRelatorios\relatorios\LocacoesPorClientes_Locacoes.jrxml ... OK.
File : C:\<caminho>\TutorialRelatorios\relatorios\LocacoesPorClientes.jrxml ... OK.
File : C:\<caminho>\TutorialRelatorios\relatorios\Clientes.jrxml ... OK.
Compilação das definições de relatórios finalizada!
compile:
Created dir: C:\<caminho>\TutorialRelatorios\dist
Copy libraries to C:\<caminho>\TutorialRelatorios\dist\lib.
Building jar: C:\<caminho>\TutorialRelatorios\dist\TutorialRelatorios.jar
To run this application from the command line without Ant, try:
java -jar "C:\<caminho>\TutorialRelatorios\dist\TutorialRelatorios.jar"
jar:
BUILD SUCCESSFUL (total time: 7 seconds)

Ou seja, ao executar o build no projeto, os arquivos .java são compilados e então cada arquivo .jrxml é compilado, gerando um .jasper em “C:\<caminho>\TutorialRelatorios\build\classes”, que no caso é a raiz do pacote do nosso projeto. Note que desta forma, sempre teremos os arquivos .jasper que correspondem às ultimas versões das definições dos relatórios. A seguir está listado o target que faz o mesmo processo para o nosso projeto Web feito na Parte 5 do tutorial. Caso queira, clique aqui para fazer o download do projeto.

build.xml (projeto Web)

<target name="-pre-dist">

    <!-- Compilação das definições dos relatórios -->
    <echo>Iniciando compilação das definições de relatórios...</echo>

    <!-- Define o classpath usado para a compilação dos relatórios -->
    <path id="jrc.classpath">
        <fileset dir="${build.classes.dir}/../lib"
                 includes="*.jar"/>
    </path>

    <!-- Define a tarefa customizada do Ant que compila
         as definições dos relatórios-->
    <taskdef name="jrc"
             classname="net.sf.jasperreports.ant.JRAntCompileTask">
        <classpath refid="jrc.classpath"/>
    </taskdef>

    <!-- Compila as definições .jrxml ==> .jasper -->
    <jrc srcdir="relatorios"
         destdir="${build.classes.dir}">
        <classpath
            refid="jrc.classpath"/>
        <include
            name="*.jrxml"/>
    </jrc>

    <echo>Compilação das definições de relatórios finalizada!</echo>

</target>

Note que o target listado acima difere um pouco do primeiro que listei (tipo do target e parte do classpath). Como exercício, tente entender porque o código é diferente e se ele pode ficar igual ou mais parecido ao primeiro target que foi mostrado. Faça mudanças no arquivo para poder entender melhor o que acontece. Os scripts que mostrei são apenas uma sugestão. Se você quiser inserir outras tarefas do Ant no build do seu projeto, dê uma olhada no manual: http://ant.apache.org/manual/index.html. Outro detalhe é que vocês conseguirão adaptar esse script para qualquer projeto, mesmo que a estrutura dele seja diferente dos projetos que criamos no tutorial.

Então é isso pessoal, espero que tenham gostado. No próximo tutorial vamos aprender os primeiros passos para trabalhar com a biblioteca JavaScript jQuery. Abraço!

Anúncios

Parte 1Parte 2Parte 3Parte 4Parte 5

Olá a todos! Nesta quinta e última parte do nosso tutorial, iremos aprender a como usar os nossos relatórios em um projeto Web. Esse parte do tutorial vai ser rápida, pois já temos praticamente tudo o que precisamos. Primeiro gostaria de pedir para quem não está acompanhando o tutorial, que baixe o projeto finalizado na Parte 4 clicando aqui. Iremos criar um novo projeto no NetBeans, só que agora do tipo Web e vamos configurá-lo com base no que já fizemos no nosso projeto original. Vamos lá então!

No NetBeans, vá em File -> New Project. No assistente de criação de projetos, escolha “Java Web” na lista de categorias e na lista de tipos de projetos, escolha “Web Application”. Clique em “Next”. Em “Project Name” dê o nome do projeto. Eu sugiro “TutorialRelatoriosWeb” (sem as aspas). Em “Project Location” escolha onde o projeto vai ser salvo. Eu vou deixar na mesma pasta do projeto original. Marque a opção “Use Dedicated Folder for Storing Libraries” e deixe o valor padrão (.\lib). Se quiser, marque a opção “Set as Main Project”. Clique em “Next”.

No próximo passo, onde é configurado o servidor que a aplicação vai ser executada, eu vou deixar o Tomcat escolhido. Se vocês preferirem usar outro servidor, não tem problema, basta selecioná-lo na lista. Deixe desmarcada a opção “Use dedicated library folder for server JAR files”. Em “JavaEE version”, deixe escolhida a versão padrão, pois não precisamos nos preocupar com isso no nosso projeto de testes. No meu caso, ficou selecionado Java EE 5. Em “Context Path” deixe o valor sugerido. No meu caso, é “/TutorialRelatoriosWeb”. Como não vamos usar nenhum framework MVC, você já pode clicar em “Next”. Feito isso, o projeto será criado e será aberto no NetBeans.

Com o projeto criado, acesse suas propriedades clicando com botão direito na raiz do projeto e escolhendo a opção “Properties”, que é a última da lista. Em “Categories” procure pelo item “Run” e selecione-o. Desmarque a opção “Deploy on Save” para evitar que seja feito um deploy a cada vez que salvarmos algo do nosso projeto. Já que estamos aqui, vamos aproveitar para configurar as bibiliotecas. Não vou colocar as figuras desse processo, pois já foi explicado nas primeiras partes do tutorial.

Selecione o item “Libraries” na lista de categorias e clique no botão “Add Library”. Primeiro vamos importar o driver do MySQL que vamos utilizar. Na janela que foi aberta, clique no botão “Import”. Procure pela biblioteca “MySQL JDBC Driver”, selecione-a e clique no botão “Import Library”. A biblioteca vai ser importada e aparecerá na janela anterior, mas ela ainda não foi inserida no projeto. Antes de a inserirmos, vamos criar a biblioteca do JasperReports. Para isso, clique no botão “Create…”. Em “Library Name” entre com o valor “JasperReports-3.7.5” (sem as aspas) e clique em “OK”. Note que eu vou manter a versão do JasperReports utilizado nas partes anteriores do tutorial, sendo assim sua versão pode variar dependendo de quando você estiver seguindo esse tutorial, visto que novas versões do JasperReports são lançadas frequentemente. Se a versão que você estiver usando for mais nova, vamos dizer, 3.7.6, defina um nome da biblioteca que reflita a versão utilizada, ou seja “JasperReports-3.7.6”.

Feito isso, a janela “Customize Library” será exibida. Clique no botão “Add JAR/Folder”. Como já fizemos isso uma vez nas partes anteriores do tutorial, o projeto original já tem essa biblioteca configurada com os JARs necessários. Então vamos usá-los. Procure pela pasta do projeto original (TutorialRelatorios). Dentro dela, entre na pasta “lib”. Dentro da pasta “lib”, existirá uma pasta chamada “JasperReports-3.7.5”. O número da versão pode variar de acordo com a sua versão. Entre nela, selecione todos os JARs e clique no botão “Add JAR/Folder”. O NetBeans vai perguntar se você quer criar um diretório com o nome da biblioteca dentro da pasta “lib” do projeto atual (TutorialRelatoriosWeb). Diga que sim e os JARs serão listados na janela “Customize Library”. Clique em OK.

Novamente a janela “Add Library” será exibida, agora contendo a também a biblioteca do JasperReports que acabamos de configurar. Selecione tanto a biblioteca do JasperReports quanto a biblioteca do MySQL e clique no botão “Add Library”. Agora as bibliotecas serão adicionadas no projeto.

Ainda na janela de propriedades, procure a categoria “Sources” (primeira) e selecione-a. Vamos criar agora o diretório onde guardaremos os nossos fontes do relatório. Na tabela “Source Package Folders”, clique no botão “Add Folder…”. Serão exibidas os diretórios contidos no projeto. Crie então uma nova pasta, chamada “relatorios” (sem acentos e sem aspas), selecione-a e clique em “Open”. A pasta será referenciada na tabela. Clique duas vezes na célula correspondente à coluna “Label” da pasta, preencha com “Relatórios” (sem as aspas) e tecle <ENTER> para trocar o “Label” da pasta. Esse “Label” vai ser utilizado para mostrar a pasta de relatórios na árvore do projeto.

Estamos quase lá. Por fim, ainda na janela de propriedades, selecione a categoria “Packaging”, dentro da categoria “Build”. Em “Exclude From WAR File”, adicione uma vírgula e o valor “**./*.jrxml” (sem as aspas). Isso fará com que os nossos arquivos fonte de relatórios não sejam empacotados no arquivo WAR. O valor final do campo deve ficar assim: “**/*.java,**/*.form, **/*.jrxml” (sem as aspas). Pronto! Clique em OK na janela de propriedades e aguarde o NetBeans escanear as novas configurações do projeto.

Agora, abra o projeto anterior, vá na pasta de “Relatórios” dele, copie o arquivo “ClientesPorNome.jrxml” e cole na pasta “Relatórios” do novo projeto. Ainda não feche o projeto anterior. No projeto atual, abra o relatório que foi copiado e faça um Preview dele para ver se está tudo ok. Lembre-se que o datasource correto (Sakila – JDBC) tem que estar selecionado lá na barra de ferramentas do NetBeans. Se o relatório for renderizado e os dados aparecerem é porque está tudo ok.

Até agora nenhuma novidade. Criamos e configuramos o novo projeto e copiamos e testamos o arquivo de relatório que já fizemos para o novo projeto. Agora vamos às novidades.

Vamos criar um Servlet que vai ser responsável em pegar os possíveis dados do request que serão usados como parâmetros para os relatórios e invocar o JasperReports para criar o relatório. O funcionamento é parecido com o que fizemos no nosso programa desktop, entretanto agora não iremos mais criar um JFrame para exibir os relatórios, pois estamos usando um navegador não é mesmo? O que o nosso Servlet vai fazer é criar diretamente um arquivo .pdf do relatório e mandar exibir no navegador – caso haja algum plugin para leitura de PDF instalado – ou então o navegador vai sugerir que você faça o download do arquivo gerado.

Em “Source Packages”, crie três pacotes: “tutorialrelatoriosweb.jdbc”, “tutorialrelatoriosweb.servlets” e “tutorialrelatoriosweb.util” (todos sem as aspas). Vá no projeto anterior, no pacote “tutorialrelatorios.jdbc”, copie a classe ConnectionFactory e cole no pacote “tutorialrelatoriosweb.jdbc” do novo projeto. Se quiser, feche o projeto anterior. Agora no novo projeto, vá na pasta “tutorialrelatoriosweb.util” e crie uma classe com o nome de “ReportUtils” (sem as aspas). Ainda não vamos implementar nada nela. Feito isso, clique com o botão direito no pacote “tutorialrelatoriosweb.servlets”, vá em New -> Servlet. Se a opção Servlet não estiver sendo exibida, selecione “Other” e em “Categories” selecione “Web” e em “File Types” escolha “Servlet” e clique em “Next”.

O assistente para criar um novo Servlet será exibido. Em “Class Name” preencha com “ReportServlet” (sem as aspas) e clique em “Next”. Tanto “Servlet Name” quanto “URL Pattern” vão ser deixados da forma que o NetBeans sugeriu, ou seja, “ReportServlet” e “/ReportServlet” respectivamente. Clique em “Finish”.

O NetBeans vai gerar por padrão uma implementação padrão do método processRequest(…). Faça com que o seu fique assim:

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

    OutputStream out = null;

    // aqui nós geramos o relatório...

    if ( out != null ) {
        out.close();
    }

}

Note que ainda não implementamos o método processRequest(…). Da mesma forma que fizemos no projeto anterior, vamos agora criar um método utilitário na classe ReportUtils que vai ser responsável em gerar o relatório. Segue a implementação comentada da classe ReportUtils.

tutorialrelatoriosweb.util.ReportUtils.java

package tutorialrelatoriosweb.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporter;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.export.JRPdfExporter;

/**
 * Classe com métodos utilitários para gerar relatórios.
 *
 * @author David Buzatto
 */
public class ReportUtils {

    /**
     * Gera o relatório em PDF.
     *
     * @param inputStream InputStream que contém o relatório.
     * @param parametros Parâmetros utilizados pelo relatório.
     * @param conexao Conexão utilizada para a execução da query.
     * @param response HttpServletResponse que será usado como base para
     * gerar o relatório.
     * @return O OutputStream do HttpServletResponse passado.
     * @throws JRException Caso ocorra algum problema na geração do relatório.
     * @throws IOException Caso ocorra algum problema na obtenção do
     * OutputStream.
     */
    public static OutputStream createPDFReport(
            InputStream inputStream,
            Map<String, Object> parametros,
            Connection conexao,
            HttpServletResponse response ) throws JRException, IOException {

        // configura o content type do response
        response.setContentType( "application/pdf" );

        // obtém o OutputStream para escrever o relatório
        OutputStream out = response.getOutputStream();

        /*
         * Cria um JasperPrint, que é a versão preenchida do relatório,
         * usando uma conexão.
         */
        JasperPrint jasperPrint = JasperFillManager.fillReport(
                inputStream, parametros, conexao );

        // Exporta em PDF, escrevendo os dados no output stream do response.
        JRExporter exporter = new JRPdfExporter();
        exporter.setParameter( JRExporterParameter.JASPER_PRINT,
                jasperPrint );
        exporter.setParameter( JRExporterParameter.OUTPUT_STREAM,
                out );

        // gera o relatório
        exporter.exportReport();

        // retorna o OutputStream
        return out;

    }

}

Como vocês podem perceber, o método createPDFReport(…) da classe ReportUtils gera um relatório em PDF e o escreve no OutputStream do response do Servlet. Caso vocês queiram outros tipos de exportação, basta mudar o tipo do exportador. Clicando aqui, vocês podem ver a documentação da interface JRExporter e de todas as classes que a implementam. Note que ao mudar o exportador, você também precisa alterar o content type do response para refletir o tipo de arquivo gerado.

Vamos agora atualizar o nosso Servlet. O método processRequest(…) vai ficar assim:

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

    OutputStream out = null;

    // obtém o relatório compilado
    InputStream inputStream = getClass().getResourceAsStream( "/ClientesPorNome.jasper" );

    // preenche o mapa de parâmetros
    Map<String, Object> parametros = new HashMap<String, Object>();
    parametros.put( "primeiroNome", "D%" );

    try {

        // gera o relatório e atribui o OutputStream gerado
        out = ReportUtils.createPDFReport( inputStream, parametros,
                ConnectionFactory.getSakilaConnection(), response );

    } catch ( SQLException exc ) {
        exc.printStackTrace();
    } catch ( JRException exc ) {
        exc.printStackTrace();
    } finally {

        // se não aconteceu nenhum problema, fecha o output stream
        if ( out != null ) {
            out.close();
        }

    }

}

Com isso feito, rode a aplicação e aponte o navegador para o endereço “http://localhost:8084/TutorialRelatoriosWeb/ReportServlet&#8221; (sem as aspas). Por padrão o Tomcat usado em desenvolvimento no NetBeans roda na porta 8084. Certifque-se que o seu está rodando nesta porta e se não estiver, use a porta correta. Se você seguiu corretamente o tutorial até aqui, será gerado então um .pdf com todos os clientes que tenham o primeiro nome iniciando com a letra “D” (veja o parâmetro “primeiroNome” passado para o relatório).

Note que agora, para passar parâmetros para o relatório, basta você obter os parâmetros pelo request e então adicionar os parâmetros desejados no mapa de parâmetros do relatório. Se quiser outros tipos de exportação, por exemplo, para Excel, basta criar um novo método na classe ReportUtils, que configura o content type apropriado (“application/ms-excel”) e o exportador necessário (JRXlsExporter ou JRXlsxExporter). Tanto a passagem de parâmetros quanto a geração de outros tipos de arquivos ficam como exercício para vocês. O Servlet ReportServlet pode ser generalizado também, permitindo que o nome do arquivo do relatório a ser gerao seja passado via request :).

Com isso terminamos nosso tutorial sobre relatórios em Java! Espero que tenham gostado! Para baixar o projeto criado nesta parte, clique aqui. Nos próximos tutoriais iremos aprender a usar a biblioteca JavaScript jQuery, que é extremamente útil e facilita muito a nossa vida.

Então é isso pessoal! Grande abraço a todos! Até a próxima 😉

Parte 1Parte 2Parte 3Parte 4Parte 5


Olá pessoal, hoje vamos aprender como configurar um projeto no FlashDevelop para trabalhar com um backend em Java. Para acelerar o processo, iremos utilizar como base tanto o projeto do backend feito no NetBeans quanto o projeto do frontend feito no Flash Builder. Então vamos lá!

Vamos começar pelo FlashDevelop. Vá no menu Project e escolha New Project. Na janela New Project, escolha Flex 4 Project. Em Name, entre com “IntegracaoFlexJavaComJanelasFD” (sem as aspas). Em location, escolha o diretório onde você está salvando o projeto do NetBeans e os projetos que fizemos no Flash Builder. No meu caso o caminho é “C:\Users\David\Documents\Java\Flex”. O campo package pode ficar vazio. Deixe a opção “Create directory for project” e clique em OK. Veja a Figura abaixo.

 

Figura 1

Criando um projeto no FlashDevelop

 

Agora vamos copiar todos os arquivos de código fonte do nosso projeto do Flash Builder. Para isso, abra o Flash Builder e localize o projeto. Vá na pasta “src”, selecione os pacotes “entidades” e “gui”, clique com o botão direito e escolha “Copy”. Veja a Figura abaixo.

 

Figura 2

Copiando o código do projeto do Flash Builder

 

Com o código copiado, volte ao FlashDevelop, clique com o botão direito na pasta “src”, escolha Edit > Paste. Veja a Figura abaixo.

 

Figura 3

Colando o código do projeto do Flash Builder no projeto do FlashDevelop

 

Fazendo isso, todo o código fonte do projeto do Flash Builder será colado dentro do projeto do FlashDevelop. Agora precisamos configurar nossa aplicação padrão. No FlashDevelop, a aplicação padrão (default application) fica marcada com flexinha verde. No nosso projeto, a aplicação padrão atual é a Main.mxml. Vamos mudar então a aplicação padrão para a Principal.mxml. Para isso, clique com o botão direito no arquivo Principal.mxml e escolha “Always Compile”. Você vai perceber que a flexinha vai passar para o Principal.mxml. Agora apague o arquivo Main.mxml (botão direito no arquivo, Edit > Delete).

Até agora criamos um novo projeto do FlashDevelop, copiamos nossos arquivos fonte e configuramos nossa aplicação principal (default application), mas ainda precisamos realizar alguns passos:

  1. Apontar o compilador do Flex para o services-config.xml, fazendo com que os serviços configurados sejam “enxergados” pelo .swf compilado;
  2. Fazer algumas alterações no services-config.xml;
  3. Configurar o FlashDevelop para copiar os arquivos do build para a nossa pasta dos arquivos swf no NetBeans;
  4. Por fim, iremos configurar o nosso index.jsp para redirecionar para a página que contém o arquivo .swf.

Então vamos lá! No FlashDevelop, algumas configurações ficam mais “escondidas” do que no Flash Builder. A primeira é relacionada à compilação dos serviços. Na verdade, quando usamos o Flash Builder, as opções da localização do arquivo services-config.xml e outras relacionadas à utilização de serviços remotos via AMF, se tornam parâmetros do compilador (veja nas propriedades do projeto do Flash Builder). Então temos que configurar isso no nosso projeto no FlashDevelop. Para isso, clique com o botão direito no seu projeto (IntegracaoFlexJavaGUIComJanelasFD) e escolha Properties.

A janela de propriedades do projeto abrirá a última aba da janela é a “Compiler Options”. Clique nela. Veja a Figura abaixo.

 

Figura 4

Opções do compilador

 

Nós vamos mexer na primeira “propriedade”, a “Additional Compiler Options”. Para isso, selecione a propriedade e clique no botão “…” para abrir o editor. No diálogo que abriu, inseria o seguinte valor:

-services C:\Users\David\Documents\Java\Flex\IntegracaoFlexJava\web\WEB-INF\flex\services-config.xml
-context-root /IntegracaoFlexJava

Antes de dar OK, vamos à explicações. O parâmetro -services é usado para apontar para o arquivo services-config.xml que está contido no projeto do backend em Java. No meu caso, o projeto do backend está localizado em “C:\Users\David\Documents\Java\Flex\”, você vai precisar localizar o seu projeto no diretório que você escolheu anteriormente. Por fim, o segundo parâmetro é o -context-root, onde devemos preencher com a raiz do contexto do nosso backend, que no nosso caso é /IntegracaoFlexJava. Agora que você já entendeu para que serve cada parâmetro e já alterou o -services para apontar para o seu services-config.xml, dê OK. O resultado deve ser parecido com o mostrado na Figura abaixo.

 

Figura 5

Opções do compilador alteradas

 

Se estiver tudo certo, você pode então dar OK na janela de propriedades, alterando assim as opções do compilador do Flex. Até agora, configuramos para o compilador enxergar o services-config.xml, mas vamos precisar – infelizmente – fazer uma pequena alteração nesse arquivo de configuração… O Flash Builder consegue inserir parâmetros no arquivo em tempo de compilação, mas o FlashDevelop não. Então o que seria automático no Flash Builder vai ter que ser manual ao usar o FlashDevelop. Vamos por a mão na massa então.

Abra o projeto do backend no NetBeans e procure pelo arquivo services-config.xml (WEB-INF/flex/services-config.xml). Ao abrir  esse arquivo XML, procure pela tag “<channels>”. Nessa tag são configurados os canais do AMF, ou seja, onde o serviços de serialização/deserialização do AMF são encontrados. Por padrão, estão definidos três canais (my-amf, my-secure-amf e my-polling-amf). Estamos usando apenas o primeiro canal, o my-amf, então é nele que vamos mexer. Primeiro copie toda a definição do canal, cole logo abaixo e comente a segunda definição. Você vai ficar com algo assim:

services-config.xml (editando)

...
<channels>

        <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
            <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>

        <!--
        <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
            <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>
        -->

        <!-- outros canais aqui... -->

</channels>
...

O que vamos alterar é a URL do endpoint. Note que na URL temos três parâmetros: {server.name}, {server.port} e {context.root}. Quando usamos o Flash Builder, ele preenche os três parâmetros em tempo de compilação, mas o FlashDevelop só “consegue” preencher o parâmetro {context.root} (lembram do parâmetro -context-root que alteramos nas opções do compilador?). Os outros dois parâmetros vamos ter que alterar manualmente. Eu ainda não encontrei onde fazer isso automaticamente no FlashDevelop, então não sei se existe essa opção de fazer o preenchimento dos outros parâmetros automaticamente. Se alguém encontrar, é só avisar ;).

Em {server.name} vamos ter que colocar o endereço do nosso servidor e em {server.port} a porta do servidor. Sendo assim, o segue o código alterado do services-config.xml.

services-config.xml (final)

...
<channels>

        <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
            <endpoint url="http://localhost:8084/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>

        <!--
        <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
            <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>
        -->

        <!-- outros canais aqui... -->

</channels>
...

Muito bem, salve o arquivo. Com isso, a compilação dos serviços irá adicionar os caminhos apropriados para a utilização dos serviços. Vamos agora configurar o FlashDevelop para copiar os arquivos do build (resultado da compilação do projeto) para dentro da pasta swf do nosso projeto do backend. Primeiro, vá no NetBeans e apague TODO o conteúdo da pasta swf. Volte ao FlashDevelop e acesse novamente as propriedades do projeto (botão direito no projeto e escolha Properties).

Nós poderíamos alterar apenas o caminho para a criação do arquivo de saída, mas queremos que todo o resultado do build (swf + outros arquivos) sejam copiados para a pasta swf do projeto do backend. Então vamos lá. Na aba “Build” vamos adicionar um comando no “Post-Build Command Line” para copiar os arquivos de build para o nosso projeto do backend. No Windows, o comando para copiar todos os arquivos de um diretório de forma recursiva é o xcopy. Então vamos adicionar o comando para copiar todos os arquivos da pastas bin do projeto do FlashDevelop para a pasta “swf” do projeto do backend. Segue então o comando e a Figura onde é mostrado o comando inserido nas propriedades do projeto do FlashDevelop. Lembre-se de marcar a opção “Always execute”.

xcopy .\bin ..\IntegracaoFlexJava\web\swf /E /Y

 

Figura 6

Comando para executar após o build do projeto

 

Então usamos o comando xcopy, para copiar o conteúdo da pasta bin para a pasta swf do projeto do backend (note os caminhos relativos). As opções /E e /Y especificam que devem ser copiados todos os arquivos recursivamente (/E) e que os arquivos devem ser substituidos sem confirmação (/Y).

Dê OK na janela de propriedades, e faça o build do projeto usando o botão com o ícone de engrenagem, na barra de ferramentas do FlashDevelop. Verifique se os arquivos da pasta do projeto do FlashDevelop foram copiados para a pasta swf do projeto do backend. Se foram copiados, ótimo, está tudo OK. Se não foram, verifique os passos do tutorial novamente para ver onde errou.

Estamos quase lá, falta apenas mudar o nosso index.jsp para apontar para o arquivo html gerado pelo FlashDevelop. Abra então o index.jsp do projeto do backend e altere a tag meta para recionar para o index.html (gerado pelo FlashDevelop, na pasta bin). O meta vai ficar assim:

Meta alterado

<meta http-equiv="Refresh" content="0; url=swf/index.html>

Execute o projeto para testar. Você vai perceber que o swf não vai ocupar todo a página, mas essa correção fica como exercício. Nesse tutorial fizemos a migração toda na mão, mas poderíamos também usar o assistente de importação do FlashDevelop (Menu Project > Import Project…), mas isso também fica como exercício 😉

Então é isso, finalizamos mais um tutorial. Espero que tenham gostado!

Abraços!

%d blogueiros gostam disto: